# 动态权限
动态授权指的是:当系统资源、或者用户角色发生变动的时候,用户权限动态更新,即刻生效。
也就说在以下场景下,需要动态刷新系统权限逻辑:
- 系统资源变更。如:新增系统资源、修改了资源的 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("参数错误");
}
}
详细实现细节,请参考源码