Spring Security Voter 鑒權(quán)
Spring Security中,系統(tǒng)進(jìn)行認(rèn)證以后浓领,獲得了當(dāng)前的Authorities
立倍,緊接著饭玲,Spring Security會進(jìn)行鑒權(quán)厅篓,判斷他是否有權(quán)限惯驼。
這個判斷主要通過投票管理器+投票器實現(xiàn)论笔。
投票器實現(xiàn)某一個條件的權(quán)限判斷徘意,投票管理器設(shè)置策略汁雷,對多個投票器的判斷結(jié)果進(jìn)行綜合净嘀。
整個認(rèn)證鑒權(quán)的代碼流程圖报咳,如下:
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
暑刃。投票管理器分析投票器的返回結(jié)果,并通過你定義的策略膜眠,決定最終的投票結(jié)果岩臣。比如:MyDecisionManagerUnanimous
是一票反對,MyDecisionManagerAffirmative
是一票通過柴底。
投票管理器
自己創(chuàng)建MyDecisionManagerAffirmative
MyDecisionManagerUnanimous
婿脸,代碼基本來自AffirmativeBased
UnanimousBased
。
投票器
WebExpressionVoter
會對當(dāng)前url
進(jìn)行分析柄驻,符合WebSecurityConfig
中的自定義權(quán)限就返回ACCESS_GRANTED
狐树。也可以將WebSecurityConfig
中的權(quán)限定義存放到數(shù)據(jù)庫中,然后重寫一個WebExpressionVoter
鸿脓,進(jìn)行分析抑钟,我這里就省略了。
我們新增了DataVoter
的分析野哭,即數(shù)據(jù)權(quán)限的分析在塔。這里僅僅舉個例子,就是用戶admin2
有權(quán)限拨黔。
//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;
}
//判斷是否匿名用戶蛔溃,是的話不判斷權(quán)限
Boolean anoymouse = authentication.getAuthorities().stream()
.anyMatch(i->{return i.toString()=="ROLE_ANONYMOUS";});
if (anoymouse){
return ACCESS_GRANTED;
}
//如果是需要驗證的頁面,只有用戶admin2有權(quán)限(原諒我的粗糙)
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;
}
}
完畢篱蝇。