1. 程式人生 > >SpringBoot集成Spring Security(3)——異常處理

SpringBoot集成Spring Security(3)——異常處理

賬戶 cat abs dto hub ror mit 轉載 app

源碼地址:https://github.com/jitwxs/blog_sample
文章目錄

一、常見異常
二、源碼分析
三、處理異常
不知道你有沒有註意到,當我們登陸失敗時候,Spring security 幫我們跳轉到了 /login?error Url,奇怪的是不管是控制臺還是網頁上都沒有打印錯誤信息。

技術分享圖片

這是因為首先 /login?error 是 Spring security 默認的失敗 Url,其次如果你不手動處理這個異常,這個異常是不會被處理的。

一、常見異常

我們先來列舉下一些 Spring Security 中常見的異常:

UsernameNotFoundException(用戶不存在)

DisabledException(用戶已被禁用)
BadCredentialsException(壞的憑據)
LockedException(賬戶鎖定)
AccountExpiredException (賬戶過期)
CredentialsExpiredException(證書過期)

以上列出的這些異常都是 AuthenticationException 的子類,然後我們來看看 Spring security 如何處理 AuthenticationException 異常的。

二、源碼分析

我們知道異常處理一般在過濾器中處理,我們在 AbstractAuthenticationProcessingFilter 中找到了對 AuthenticationException 的處理:

(1)在 doFilter() 中,捕捉了 AuthenticationException 異常,並交給了 unsuccessfulAuthentication() 處理。

技術分享圖片

(2)在 unsuccessfulAuthentication() 中,轉交給了 SimpleUrlAuthenticationFailureHandler 類的 onAuthenticationFailure() 處理。

技術分享圖片

(3)在onAuthenticationFailure()中,首先判斷有沒有設置defaultFailureUrl。

如果沒有設置,直接返回 401 錯誤,即 HttpStatus.UNAUTHORIZED 的值。

如果設置了,首先執行 saveException() 方法。然後判斷 forwardToDestination ,即是否是服務器跳轉,默認使用重定向即客戶端跳轉。

技術分享圖片

(4)在 saveException() 方法中,首先判斷forwardToDestination,如果使用服務器跳轉則寫入 Request,客戶端跳轉則寫入 Session。寫入名為 SPRING_SECURITY_LAST_EXCEPTION ,值為 AuthenticationException。

技術分享圖片

至此 Spring security 完成了異常處理,總結一下流程:

–> AbstractAuthenticationProcessingFilter.doFilter()

–> AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication()

–> SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()

–> SimpleUrlAuthenticationFailureHandler.saveException()

三、處理異常

上面源碼說了那麽多,真正處理起來很簡單,我們只需要指定錯誤的url,然後再該方法中對異常進行處理即可。

(1)指定錯誤Url,WebSecurityConfig中添加.failureUrl("/login/error")

...

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 如果有允許匿名的url,填在下面
// .antMatchers().permitAll()
.anyRequest().authenticated()
.and()
// 設置登陸頁
.formLogin().loginPage("/login")
// 設置登陸成功頁
.defaultSuccessUrl("/").permitAll()
// 登錄失敗Url
.failureUrl("/login/error")
// 自定義登陸用戶名和密碼參數,默認為username和password
// .usernameParameter("username")
// .passwordParameter("password")
.and()
.logout().permitAll()
// 自動登錄
.and().rememberMe()
.tokenRepository(persistentTokenRepository())
// 有效時間:單位s
.tokenValiditySeconds(60)
.userDetailsService(userDetailsService);

// 關閉CSRF跨域
http.csrf().disable();
}
...

  


(2)在Controller中處理異常

@RequestMapping("/login/error")
public void loginError(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("text/html;charset=utf-8");
AuthenticationException exception =
(AuthenticationException)request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
try {
response.getWriter().write(exception.toString());
}catch (IOException e) {
e.printStackTrace();
}
}

  


我們首先獲取了 session 中的 SPRING_SECURITY_LAST_EXCEPTION 。為了演示,我只是簡單的將錯誤信息返回給了頁面。運行程序,當我們輸入錯誤密碼時:

技術分享圖片
---------------------
作者:Jitwxs
來源:CSDN
原文:https://blog.csdn.net/yuanlaijike/article/details/80250389
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

SpringBoot集成Spring Security(3)——異常處理