代碼硬編碼
在代碼中實現(xiàn)適用于簡單的權(quán)限控制,一般只是限制是否登錄,或有簡單的角色
登錄與不登錄
http.authorizeRequests()
//不需要登錄的路徑
.antMatchers("/orders","/login").permitAll()
//其它需要
.anyRequest().authenticated();
簡單角色
http.authorizeRequests()
//不需要登錄的路徑
.antMatchers("/orders","/login").permitAll()
//擁有ADMIN這個角色才能訪問
.antMatchers("/manager").hasRole("ADMIN")
//其它需要
.anyRequest().authenticated();
//此時用戶的GrantedAuthority 為ROLE_ADMIN
new User("admin", passwordEncoder.encode("123456"),"ROLE_SECRET");
在Restful API中,有可能針對同一個請求路徑,不同的請求方式需要不同的權(quán)限,此外當(dāng)URL中存在參數(shù)時 如DELETE請求 user/{userId} 都是刪除用戶,整體URL是變化的
http.authorizeRequests()
//路徑匹配user/* 并且是delete請求 需要有ADMIN角色才能訪問
.antMatchers(HttpMethod.DELETE,"/user/*").hasRole("ADMIN")
//其它需要
.anyRequest().authenticated();
或者也可以搭配使用
http.authorizeRequests()
.antMatchers(HttpMethod.DELETE,"/user/*").access("hasRole('ROLE_ADMIN') and hasRole('ROLE_SUPER') or hasIpAddress('127.0.0.1')")
.anyRequest().authenticated();
ExpressionUrlAuthorizationConfigurer 定義的權(quán)限表達(dá)式
從數(shù)據(jù)庫獲取
用戶權(quán)限較復(fù)雜時,不可能把每個url需要啥權(quán)限都配置在代碼里,配置在代碼里也無法實現(xiàn)動態(tài)的修改權(quán)限,實現(xiàn)方式貌似有兩種,一種是重寫 SecurityMetadataSource 和 AccessDecisionManager ,在springSecurity過濾器鏈中,最后一個過濾器FilterSecurityInterceptor 中會調(diào)用 AccessDecisionManager 的 decide 方法,來確定當(dāng)前請求是否通過.這種方法寫著比較難受,網(wǎng)上也有很多,就不寫了.另一種就是利用SPEL 如下,表達(dá)式內(nèi)的方法在 WebExpressionVoter 的 vote方法中被調(diào)用
@Component("accessDecisionService")
public class AccessDecisionService {
private AntPathMatcher antPathMatcher = new AntPathMatcher();
public boolean hasPermission(HttpServletRequest request, Authentication auth){
UserDetails user = (UserDetails) auth.getPrincipal();
String userName=user.getUsername();
List<String> urls=new ArrayList<>();
//todo: 根據(jù)用戶名查出能訪問哪些url, urls=findUrlByUserName()
for (String url : urls) {
if (antPathMatcher.match(url, request.getRequestURI())){
return true;
}
}
return false;
}
}
http.authorizeRequests()
.anyRequest()
.access("@accessDecisionService.hasPermission(request , authentication)");