Java 如何避免数据库查询以验证用户操作

Java 如何避免数据库查询以验证用户操作,java,Java,以下是验证当前操作的两种方法 在用户会话中保存登录时的用户详细信息。对于登录后的每个操作,每次检查用户是否具有角色和权限。需要查询数据库,因为管理员可以随时更改用户的权限。查询当前用户的角色和权限,并每次验证操作 在用户会话中保存登录时的用户详细信息。对于登录后的每个操作,只检查与会话关联的角色/权限。不需要查询数据库。但是,如果管理员或任何用户更改了来自不同国家/地区的当前用户的权限,则会使应存储在某处的当前用户会话无效 以上哪一项是针对上述问题的最佳方法?如何实现 许多应用程序的每一个动作都

以下是验证当前操作的两种方法

  • 在用户会话中保存登录时的用户详细信息。对于登录后的每个操作,每次检查用户是否具有角色和权限。需要查询数据库,因为管理员可以随时更改用户的权限。查询当前用户的角色和权限,并每次验证操作

  • 在用户会话中保存登录时的用户详细信息。对于登录后的每个操作,只检查与会话关联的角色/权限。不需要查询数据库。但是,如果管理员或任何用户更改了来自不同国家/地区的当前用户的权限,则会使应存储在某处的当前用户会话无效

  • 以上哪一项是针对上述问题的最佳方法?如何实现

    许多应用程序的每一个动作都会影响数据库

    某些应用程序使会话无效

    以上两个方面的任何参考或代码片段都会有所帮助


    不确定除了这两种方法之外是否还有其他方法可用。您可以采用一种混合方法:在用户会话中缓存角色+权限N分钟,然后使缓存无效并从数据库中重新加载它们。因此,用户权限不正确的时间不会超过N分钟

    另一种方法是在内存和用户会话中存储每个角色的上次更新日期+时间。当管理员更新角色权限时,您将此角色的“更新日期+时间”设置为“现在”。此外,对于每个用户操作,您首先检查存储在会话中的角色的“加载日期+时间”是否早于存储在内存中的全局更新日期+时间。若该角色较旧,则需要从数据库重新加载该角色及其权限

    只有在

  • 您只有一个应用程序实例(没有分发),或者共享数据的速度比访问数据库快得多(某种分布式缓存?)
  • 权限由管理员通过同一应用程序更改
  • 您的安全模型并不太复杂
  • 假设您有一个对象
    roleUpdateTimes
    ,其中包含从角色到其上次更新日期+时间的映射(或者
    null
    ,如果角色自上次重新启动后未更新)

    管理员更新角色时,将执行以下操作:

    roleUpdateTimes.updated(roleName);
    
    其中
    updated()

    public void updated(String roleName) {
        map.put(roleName, new Date());
    }
    
    map
    在这里可能是一个
    ConcurrentHashMap
    ,这样我们就有了一个正确的行为,知道map将被不同的线程访问

    对于用户,您可以在
    过滤器中设置以下内容:

    Date roleDate = getRoleDateFromSession(session);
    String roleName = getRoleNameFromSession(session);
    if (roleUpdateTimes.roleIsStale(roleName, roleDate)) {
        ... reload role permissions from database and save them to session
        saveRoleDateToSession(session, new Date());
    }
    


    此外,您可能需要在启动时加载
    map
    :只需为每个已知角色放置
    new Date()

    我对第二种方法的更新日期+时间很满意。谢谢你宝贵的时间,非常感谢你友好的细节
    public void roleIsStale(String roleName, Date snapshotDate) {
        Date updateDate = map.get(roleName)) {
        if (updateDate == null) {
            // role was not changed by admin, it's not stale
            return false;
        }
        return updateDate.after(snapshotDate);
    }