原文鏈接
問題:
在使用Spring security時(shí)使用postman訪問登錄失敗能得到自定義錯誤信息401,但是使用瀏覽器訪問的時(shí)候,當(dāng)?shù)卿洺晒r(shí)能正常進(jìn)入自定義配置類,但是失敗是直接給瀏覽器返回一個狀態(tài)碼302,并且通過查看斷點(diǎn)并不能進(jìn)入配置類
原因:
spring security對未認(rèn)證的訪問會默認(rèn)重定向一個接口,因前后端分離,所以不能實(shí)現(xiàn)前端自定義跳轉(zhuǎn)到登陸頁面的邏輯,實(shí)際修改方案就是后臺修改spring security框架默認(rèn)的302執(zhí)行邏輯。
解決方法:
實(shí)現(xiàn)AuthenticationEntryPoint接口,覆寫commence方法,修改返回狀態(tài)值為401,修改配置。讓前端去獲取狀態(tài)碼執(zhí)行前端的邏輯。
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
}
}
commence方法的具體實(shí)現(xiàn)做了些修改:
不是直接返回401,加一些判斷再返回401
if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")){
Cookie[] cookies = request.getCookies();
if (cookies == null) { // JSESSIONID不存在了,刪除了
response.setStatus(HttpStatus.UNAUTHORIZED.value());
} else {
boolean hasJSessionid = false;
for(Cookie c : cookies) {
if (c.getName().equals("JSESSIONID")) {
hasJSessionid = true;
break;
}
}
if (!hasJSessionid) { // JSESSIONID不存在了,修改了
response.setStatus(HttpStatus.UNAUTHORIZED.value());
} else { // JSESSIONID存在,判斷是否合法
HttpSession session = request.getSession(true);
if(session.isNew()) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
}
}
}
}
@Configuration
public class BrowserSecurityConfig extends AbstractChannelSecurityConfig {
@Override
protected void configure(HttpSecurity http) throws Exception {
applyPasswordAuthenticationConfig(http);
http.apply(validateCodeSecurityConfig)
.and()
.apply(smsCodeAuthenticationSecurityConfig)
.and()
.apply(imoocSocialSecurityConfig)
.and()
.sessionManagement()
.invalidSessionStrategy(invalidSessionStrategy)
.maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions())
.maxSessionsPreventsLogin(securityProperties.getBrowser().getSession()
.isMaxSessionsPreventsLogin())
.expiredSessionStrategy(sessionInformationExpiredStrategy)
.and()
.and()
.logout()
.logoutSuccessHandler(onstepLogoutSuccessHandler)
.deleteCookies("JSESSIONID")
.and()
.authorizeRequests()
.antMatchers(
securityProperties.getBrowser().getLoginPage(),
securityProperties.getBrowser().getSignUpUrl())
.permitAll()
.anyRequest()
.authenticated()
.and()
.cors()
.and()
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint());
}
}
主要注意的代碼:
1.response.setStatus(HttpStatus.UNAUTHORIZED.value());
2..exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint());
補(bǔ)充
- AuthenticationEntryPoint 用來解決匿名用戶訪問無權(quán)限資源時(shí)的異常
- AccessDeineHandler 用來解決認(rèn)證過的用戶訪問無權(quán)限資源時(shí)的異常