史上最简单的Spring Security教程(二十二):自定义AccessDecisionManager实现简单的访问决策
在前面讲过的资源权限动态控制业务场景中,我们使用了 Spring Security 框架默认的 AccessDecisionManager,即
AffirmativeBased。能实现的访问决策即为任一 AccessDecisionVoter 授予权限,即代表授予访问权限。但是我们只添加了一个 AccessDecisionVoter ,即 RoleVoter。
既然如此,我们就可以简化一下这些逻辑,直接自定义一个新的 AccessDecisionManager,其决策逻辑为:当前请求所需的所有 ConfigAttribute 传递给 AccessDecisionVoter 进行决策,只要任一与用户拥有 GrantedAuthority 匹配,即代表授予访问权限。
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) throws AccessDeniedException {
Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication);
for (ConfigAttribute attribute : attributes) {
if (this.supports(attribute)) {
// Attempt to find a matching granted authority
for (GrantedAuthority authority : authorities) {
if (attribute.getAttribute().equals(authority.getAuthority())) {
return;
}
}
logger.warn("current user not have the '{}' attribute.", attribute);
}
}
logger.warn("current request should be have at least one of the attributes {}.", attributes);
throw new AccessDeniedException("Access is denied.");
}
这样一来,可以不用添加 RoleVoter,同时,也能满足当前的业务场景。
注意,需要保证 UserDetailsService 中授予的角色权限标识 和 SecurityMetaDataSource 中组织的请求需要的角色权限标识一致即可。
接下来修改一下 Spring Security 的配置,来尝试一下吧。
private AccessDecisionManager accessDecisionManager() {
return new AnyMatchBased();
}
启动系统,访问个人中心,此时用户拥有 User、User_2 角色,可以正常访问。
如果 User_2 角色不存在,可参考如下文章中的内容,其中有关于 User_2 角色的相关初始化sql:史上最简单的Spring Security教程(二十):自定义AccessDecisionVoter实现必须全部拥有请求所需权限才可访问的需求。
然后,删除任一角色与用户的映射关系(SYS_ROLE_USER),注意提前备份要删除的数据。再退出登录、重新登录系统,访问个人中心,发现依然可以正常访问。
关于为何要先退出登录、重新登录,前面已经讲过具体原因,可自行查看如下内容:史上最简单的Spring Security教程(二十):自定义AccessDecisionVoter实现必须全部拥有请求所需权限才可访问的需求。
最后,删除所有的角色映射关系,再退出登录、重新登录系统,访问个人中心。此时,已不能正常访问该功能。
简单版的授权决策器实现成功。
其它详细源码,请参考文末源码链接,可自行下载后阅读。
我是银河架构师,十年饮冰,难凉热血,愿历尽千帆,归来仍是少年!
如果文章对您有帮助,请举起您的小手,轻轻【三连】,这将是笔者持续创作的动力源泉。当然,如果文章有错误,或者您有任何的意见或建议,请留言。感谢您的阅读!
文章不定时更新,可微信搜索「银河架构师」,精彩内容,先睹为快!
上一篇: 经典案例——图片库
下一篇: spring aop方法拦截器链
推荐阅读
-
史上最简单的Spring Security教程(十一):url区分不同的登录失败场景
-
史上最简单的Spring Security教程(二十):AccessDecisionVoter必须全部拥有请求所需权限才可访问
-
史上最简单的Spring Security教程(四十):SecurityContextPersistenceFilter详解
-
史上最简单的Spring Security教程(十三):动态用户
-
史上最简单的Spring Security教程(十四):动态权限(自定义UserDetailsService)
-
史上最简单的Spring Security教程(十九):AccessDecisionVoter简介及自定义访问权限投票器
-
史上最简单的Spring Security教程(十五):资源权限动态控制(FilterSecurityInterceptor)
-
史上最简单的Spring Security教程(二十七):AuthenticationManager默认实现之ProviderManager详解
-
史上最简单的Spring Security教程(二十二):自定义AccessDecisionManager实现简单的访问决策
-
史上最简单的Spring Security教程(十六):FilterSecurityInterceptor详解