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

时间:2018-03-05 18:23:47

标签: java

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

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

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

  3. 上述哪一项最适合上述方法?如何实现

    许多应用程序都会针对每个操作点击数据库。

    某些申请会使会话无效......

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

    不确定除了两个

    之外是否还有其他方法可用

1 个答案:

答案 0 :(得分:0)

您可以采用混合方法:在用户会话中缓存角色+权限N分钟,然后使缓存无效并从数据库重新加载它们。因此,用户权限不会超过N分钟。

另一种方法是将每个角色的最后更新日期+时间存储在内存和用户会话中。当管理员更新角色权限时,您可以设置更新日期+时间'对于这个角色来说,现在'。此外,对于每个用户操作,您首先要检查是否加载日期+时间'存储在其会话中的角色比存储在内存中的全局更新日期+时间早。如果它较旧,则需要从数据库重新加载角色及其权限。

这只适用于

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

    当管理员更新角色时,将完成以下操作:

    roleUpdateTimes.updated(roleName);
    

    其中updated()方法只将当前日期放入地图:

    public void updated(String roleName) {
        map.put(roleName, new Date());
    }
    

    map在这里可能是ConcurrentHashMap,因此我们知道地图将被不同的线程访问,因此我们有正确的行为。

    对于用户,您可以在Filter

    中拥有以下内容
    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());
    }
    

    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);
    }
    

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