日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot整合Spring Security——第三章异常处理

發(fā)布時(shí)間:2025/1/21 javascript 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot整合Spring Security——第三章异常处理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 一、常見異常
    • 二、源碼分析
    • 三、處理異常
    • 四、拓展spring security authenticationProvider用法及關(guān)閉不隱藏UserNotFoundException的解決

不知道你有沒有注意到,當(dāng)我們登陸失敗時(shí)候,Spring security 幫我們跳轉(zhuǎn)到了 /login?error Url,奇怪的是不管是控制臺還是網(wǎng)頁上都沒有打印錯(cuò)誤信息。

這是因?yàn)槭紫?/login?error 是 Spring security 默認(rèn)的失敗 Url,其次如果你不手動(dòng)處理這個(gè)異常,這個(gè)異常是不會(huì)被處理的。

代碼地址:https://github.com/FadeHub/spring-boot-learn/tree/master/spring-boot-security-3

一、常見異常

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

  • UsernameNotFoundException(用戶不存在)
  • DisabledException(用戶已被禁用)
  • BadCredentialsException(壞的憑據(jù))
  • LockedException(賬戶鎖定)
  • AccountExpiredException (賬戶過期)
  • CredentialsExpiredException(證書過期)

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

二、源碼分析

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

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

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

(3)在onAuthenticationFailure()中,SimpleUrlAuthenticationFailureHandler實(shí)現(xiàn)類,首先判斷有沒有設(shè)置defaultFailureUrl。

如果沒有設(shè)置,直接返回 401 錯(cuò)誤,即 HttpStatus.UNAUTHORIZED 的值。

如果設(shè)置了,首先執(zhí)行 saveException() 方法。然后判斷 forwardToDestination ,即是否是服務(wù)器跳轉(zhuǎn),默認(rèn)使用重定向即客戶端跳轉(zhuǎn)。

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

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

–> AbstractAuthenticationProcessingFilter.doFilter()

–> AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication()

–> SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()

–> SimpleUrlAuthenticationFailureHandler.saveException()

三、處理異常

上面源碼說了那么多,真正處理起來很簡單,我們只需要指定錯(cuò)誤的url,然后再該方法中對異常進(jìn)行處理即可。

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

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate CustomUserDetailsService userDetailsService;@Autowiredprivate DataSource dataSource;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(authenticationProvider());}@Beanpublic DaoAuthenticationProvider authenticationProvider() {DaoAuthenticationProvider provider = new DaoAuthenticationProvider();provider.setHideUserNotFoundExceptions(false);provider.setUserDetailsService(userDetailsService);provider.setPasswordEncoder(new PasswordEncoder() {@Overridepublic String encode(CharSequence charSequence) {return charSequence.toString();}@Overridepublic boolean matches(CharSequence charSequence, String s) {return s.equals(charSequence.toString());}});return provider;}/*** 數(shù)據(jù)庫存儲(chǔ)* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login")// 設(shè)置登陸成功頁.defaultSuccessUrl("/").permitAll().failureHandler(new SimpleUrlAuthenticationFailureHandler())//登錄失敗url.failureForwardUrl("/login/error").and()// 自定義登陸用戶名和密碼參數(shù),默認(rèn)為username和password// .usernameParameter("username")// .passwordParameter("password").logout().permitAll()//基于內(nèi)存自動(dòng)登錄.and().rememberMe().tokenRepository(persistentTokenRepository()).tokenValiditySeconds(60) ;http.csrf().disable();}@Beanpublic PersistentTokenRepository persistentTokenRepository() {JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);// 如果token表不存在,使用下面語句可以初始化該表;若存在,請注釋掉這條語句,否則會(huì)報(bào)錯(cuò)。 // tokenRepository.setCreateTableOnStartup(true);return tokenRepository;}@Overridepublic void configure(WebSecurity web) throws Exception {// 設(shè)置攔截忽略文件夾,可以對靜態(tài)資源放行web.ignoring().antMatchers("/css/**", "/js/**");}}

對應(yīng)Controller

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

一定是取req.getAttribuate(“SPRING_SECURITY_LAST_EXCEPTION”)才能取出異常信息。

四、拓展spring security authenticationProvider用法及關(guān)閉不隱藏UserNotFoundException的解決

問題是用戶登錄失敗(用戶不存在或密碼錯(cuò)誤)之后,security框架直接返回的是驗(yàn)證失敗。而我的需求是將用戶不存在和密碼錯(cuò)誤區(qū)分開來,然后做不同的后續(xù)工作。

用戶不存在返回錯(cuò)誤信息為:UsernameNotFoundException
密碼錯(cuò)誤返回錯(cuò)誤信息為:BadCredentialsException

UserNotFoundException異常是在DaoAuthenticationProvider中被屏蔽掉的,而DaoAuthenticationProvider中有個(gè)屬性hideUserNotFoundExceptions,默認(rèn)是ture,也就是說要想拋出UserNotFoundException,需要把hideUserNotFoundExceptions設(shè)為false。
于是增加了一個(gè)DaoAuthenticationProvider的配置

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(authenticationProvider());}@Beanpublic DaoAuthenticationProvider authenticationProvider() {DaoAuthenticationProvider provider = new DaoAuthenticationProvider();provider.setHideUserNotFoundExceptions(false);provider.setUserDetailsService(userDetailsService);provider.setPasswordEncoder(new PasswordEncoder() {@Overridepublic String encode(CharSequence charSequence) {return charSequence.toString();}@Overridepublic boolean matches(CharSequence charSequence, String s) {return s.equals(charSequence.toString());}});return provider;}

如果我們配置DaoAuthenticationProvider一定要把

auth .userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());

這兩行代碼刪掉,否則還是不會(huì)返回我們希望的錯(cuò)誤信息!!!

總結(jié)

以上是生活随笔為你收集整理的SpringBoot整合Spring Security——第三章异常处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。