Spring Security的用法看了不少纺蛆,就大概來總結(jié)總結(jié)算利,找出一套適合直接應(yīng)用到項目的。
一证薇、為什么要用Spring Security
待補充
二度苔、Spring Security整合中的缺點
??Spring Security的主要功能是登錄驗證、訪問控制浑度。然而寇窑,由于Remember Me和訪問控制自身的缺陷,導(dǎo)致并不適用在實際的項目中俺泣。Remember Me的缺陷參考上篇文章:關(guān)于記住HTTP請求的狀態(tài)疗认;訪問控制的不足完残,主要是因為要把權(quán)限控制硬編碼在代碼中伏钠。為了解決這兩個問題,考慮引入JWT+redis(JWT)和RBAC谨设。
1.引入JWT+redis
??1)講講JWT的優(yōu)缺點熟掂。2)引入redis解決其刷新的問題有兩種方式。①時時更新 ②保存一個上次訪問時間扎拣,在JWT過期時赴肚,比較兩次時間的差值來確定,是否需要動態(tài)更新JWT二蓝。
待補充
2.引入RBAC
??RBAC的引入分三步:先設(shè)計數(shù)據(jù)庫誉券,再編寫增刪改查操作,最后將RBAC應(yīng)用到Spring Security中刊愚。前兩步就省略了踊跟,直接看第三步吧,怎么在Spring Security中使用RBAC鸥诽。
首先商玫,判斷當(dāng)前用戶所擁有的URL是否和當(dāng)前訪問的URL是否匹配
/**
* 返回權(quán)限驗證的接口
*/
public interface RbacService {
boolean hasPermission(HttpServletRequest request,Authentication authentication);
}
@Component("rbacService")
public class RbacServiceImpl implements RbacService {
private AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
Object principal = authentication.getPrincipal();
boolean hasPermission = false;
if (principal instanceof UserDetails) { //首先判斷先當(dāng)前用戶是否是我們UserDetails對象箕憾。
String userName = ((UserDetails) principal).getUsername();
Set<String> urls = new HashSet<>(); // 數(shù)據(jù)庫讀取 //讀取用戶所擁有權(quán)限的所有URL
urls.add("/whoim");
// 注意這里不能用equal來判斷,因為有些URL是有參數(shù)的拳昌,所以要用AntPathMatcher來比較
for (String url : urls) {
if (antPathMatcher.match(url, request.getRequestURI())) {
hasPermission = true;
break;
}
}
}
return hasPermission;
}
}
然后將此訪問控制配置在Spring Security中
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //表單登錄
//.loginPage("/evolutionary-loginIn.html")
.loginPage("/logintype") //如果需要身份認(rèn)證則跳轉(zhuǎn)到這里
.loginProcessingUrl("/login")
.successHandler(evolutionaryAuthenticationHandler)
.failureHandler(evolutionaryAuthenticationFailureHandler)
.and()
.authorizeRequests()
.antMatchers("/logintype",securityProperties.getBrower().getLoginPage())//不校驗我們配置的登錄頁面
.permitAll()
.anyRequest()
.access("@rbacService.hasPermission(request,authentication)") //必須經(jīng)過認(rèn)證以后才能訪問
.and().csrf().disable().addFilter(new JWTLoginFilter(authenticationManager()))
.addFilter(new JWTAuthenticationFilter(authenticationManager()));
}