Spring Security Voter 鉴权
Spring Security中,系统进行认证以后,获得了当前的Authorities
,紧接着,Spring Security会进行鉴权,判断他是否有权限。
这个判断主要通过投票管理器+投票器实现。
投票器实现某一个条件的权限判断,投票管理器设置策略,对多个投票器的判断结果进行综合。
整个认证鉴权的代码流程图,如下:
spring security
websecurity
首先,我们修改一下WebSecurityConfig
:
package com.it_laowu.springbootstudy.springbootstudydemo.core.config;
......
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
......
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests() .accessDecisionManager(accessDecisionManager())
......
}
private AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = Arrays.asList(new WebExpressionVoter(),new DataVoter() );
// return new MyDecisionManagerAffirmative(decisionVoters);
return new MyDecisionManagerUnanimous(decisionVoters);
}
}
这样,我们就把自己定义的投票器管理器MyDecisionManagerUnanimous
和两个投票器WebExpressionVoter
DataVoter
注册到了SpringSecurity
。投票管理器分析投票器的返回结果,并通过你定义的策略,决定最终的投票结果。比如:MyDecisionManagerUnanimous
是一票反对,MyDecisionManagerAffirmative
是一票通过。
投票管理器
自己创建MyDecisionManagerAffirmative
MyDecisionManagerUnanimous
,代码基本来自AffirmativeBased
UnanimousBased
。
投票器
WebExpressionVoter
会对当前url
进行分析,符合WebSecurityConfig
中的自定义权限就返回ACCESS_GRANTED
。也可以将WebSecurityConfig
中的权限定义存放到数据库中,然后重写一个WebExpressionVoter
,进行分析,我这里就省略了。
我们新增了DataVoter
的分析,即数据权限的分析。这里仅仅举个例子,就是用户admin2
有权限。
//DataVoter
package com.it_laowu.springbootstudy.springbootstudydemo.core.auth;
......
public class DataVoter implements AccessDecisionVoter<Object> {
private static final Logger logger = LoggerFactory.getLogger(DataVoter.class);
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@Override
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
if (authentication == null) {
return ACCESS_DENIED;
}
//判断是否匿名用户,是的话不判断权限
Boolean anoymouse = authentication.getAuthorities().stream()
.anyMatch(i->{return i.toString()=="ROLE_ANONYMOUS";});
if (anoymouse){
return ACCESS_GRANTED;
}
//如果是需要验证的页面,只有用户admin2有权限(原谅我的粗糙)
String username = authentication.getName();
if (StrUtil.startWith(username, "admin2", true)) {
return ACCESS_GRANTED;
}
for (ConfigAttribute attribute : attributes) {
System.out.println("attribute:"+attribute);
}
logger.debug("username:"+username);
for (ConfigAttribute attribute : attributes) {
logger.debug("attribute:"+attribute);
for (GrantedAuthority auth : authentication.getAuthorities()) {
logger.debug("auth:"+auth);
if (attribute.getAttribute().trim().equals(auth.getAuthority().trim())) {
return ACCESS_GRANTED;
}
}
}
return ACCESS_ABSTAIN;
}
}
完毕。