# 动态权限

动态授权指的是:当系统资源、或者用户角色发生变动的时候,用户权限动态更新,即刻生效。

也就说在以下场景下,需要动态刷新系统权限逻辑:

  • 系统资源变更。如:新增系统资源、修改了资源的 url 或者权限标识、删除了系统资源等;
  • 角色权限变更。如:对角色进行了授权操作、修改了角色拥有的权限等。
  • 用户角色变更。如:修改用户所属角色。

对应以上场景,Heimdall框架的实现逻辑:

  • 系统资源变更:清除所有缓存系统资源,然后重新载入;
  • 角色权限变更:角色权限变化,角色下属所有用户的权限会一起变化,这种场景下,可以先通过角色获取到下属所有用户,然后逐个清理用户权限,也可以直接全部清理所有缓存的用户权限。推荐:全部清理用户权限。
  • 用户角色变更:这种情况与角色权限变更处理逻辑相同。

# 系统资源变更

首先需要注入权限缓存 DAO

    @Autowired
    private AuthorizationMetaDataCacheDao authorizationMetaDataCacheDao;

然后,在资源的新增、修改、删除操作完成后,清理系统权限缓存,如下所示:

    //新增资源
    public SysResourceDTO save(SysResourceVO param) {
        final SysResourceEntity toSave = sysResourceMapper.voToEntity(param);
        final SysResourceEntity saved = sysResourceRepository.saveAndFlush(toSave);
        //新增加了系统权限,将缓存的系统权限清空,便于下次访问重新加载生效
        authorizationMetaDataCacheDao.clearSysAuthorities();
        return sysResourceMapper.toDto(saved);
    }
    //修改资源信息
    public SysResourceDTO update(SysResourceVO param) {
        final Optional<SysResourceEntity> toUpdate = sysResourceRepository.findById(param.getId());
        if (toUpdate.isPresent()) {
            final SysResourceEntity toUpdated = toUpdate.get();
            toUpdated.setName(param.getName());
            toUpdated.setUrl(param.getUrl());
            toUpdated.setMethod(param.getMethod());
            final SysResourceEntity updated = sysResourceRepository.saveAndFlush(toUpdated);
            //修改了系统权限,将缓存的系统权限清空,便于下次访问重新加载生效
            //严谨一些,此处应该判断一下修改的信息是否对拦截规则有影响
            //没有影响则可以不用清理缓存
            authorizationMetaDataCacheDao.clearSysAuthorities();
            return sysResourceMapper.toDto(updated);
        } else {
            throw new IllegalArgumentException("参数错误");
        }
    }
    //删除资源
     public void deleteById(String id) {
        final Optional<SysResourceEntity> toDelete = sysResourceRepository.findById(id);
        if (toDelete.isPresent()) {
            sysResourceRepository.delete(toDelete.get());
            //删除了系统权限,将缓存的系统权限清空,便于下次访问重新加载生效
            authorizationMetaDataCacheDao.clearSysAuthorities();
        } else {
            throw new IllegalArgumentException("参数错误");
        }
    }

# 角色权限变更

当对角色权限发生变动,也就是修改角色信息和删除角色信息的时候,动态清理用户权限。

    //修改角色信息
    public SysRoleDTO update(SysRoleVO param) {
        final Optional<SysRoleEntity> toUpdate = sysRoleRepository.findById(param.getId());
        if (toUpdate.isPresent()) {
            final SysRoleEntity toUpdated = toUpdate.get();
            toUpdated.setName(param.getName());
            toUpdated.setDescription(param.getDescription());
            //修改角色的权限资源
            if(null!=param.getResources()&&!param.getResources().isEmpty()){
                toUpdated.setResources(sysResourceMapper.voListToEntityList(param.getResources()));
            }
            final SysRoleEntity updated = sysRoleRepository.saveAndFlush(toUpdated);
            //角色权限资源发生变动,清理所有用户权限缓存
            //这里严谨一些,应该判断一下,是不是有资源发生变动,如果角色资源没变动,则不需要清理
            sessionDAO.clearAllUserAuthorities();
            return sysRoleMapper.toDto(updated);
        } else {
            throw new IllegalArgumentException("参数错误");
        }
    }

    //删除角色,则此角色下所有用户的权限也会相应变动
    public void deleteById(String id) {
        final Optional<SysRoleEntity> toDelete = sysRoleRepository.findById(id);
        if (toDelete.isPresent()) {
            sysRoleRepository.delete(toDelete.get());
            //角色删除后,清理所有用户的权限缓存
            sessionDAO.clearAllUserAuthorities();
        } else {
            throw new IllegalArgumentException("参数错误");
        }
    }

详细实现细节,请参考源码

上次更新:: 1/25/2021, 4:26:40 PM