Spring Security中successHandler和failureHandler使用方式
前言
successHandler和failureHandler是Spring Security中兩個(gè)較為強(qiáng)大的用來(lái)處理登錄成功和失敗的回調(diào)函數(shù),通過(guò)它們兩個(gè)我們就可以自定義一些前后端數(shù)據(jù)的交互。
successHandler
該方法有三個(gè)參數(shù)
req
:相當(dāng)與HttpServletRequestres
:相當(dāng)與HttpServletResposeauthentication
:這里保存了我們登錄后的用戶信息
進(jìn)行如下配置
.successHandler((req, resp, authentication) -> { Object principal = authentication.getPrincipal(); resp.setContentType("application/json;charset=utf-8"); PrintWriter out = resp.getWriter(); out.write(new ObjectMapper().writeValueAsString(principal)); out.flush(); out.close(); })
配置類(lèi)代碼
package com.scexample.sc.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.io.PrintWriter; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("xiaoming") .password("123456").roles("admin"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個(gè)是用來(lái)忽略一些url地址,對(duì)其不進(jìn)行校驗(yàn),通常用在一些靜態(tài)文件中。 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/aaa.html") .loginProcessingUrl("/logintest") .usernameParameter("name") .passwordParameter("passwd") .successHandler((req, res, authentication) -> { Object principal = authentication.getPrincipal(); res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(new ObjectMapper().writeValueAsString(principal)); out.flush(); out.close(); }) .permitAll() .and() .csrf().disable() ); } }
再次登錄后
failureHandler
該方法有三個(gè)參數(shù)
req
:相當(dāng)與HttpServletRequestres
:相當(dāng)與HttpServletResposee
:這里保存了我們登錄失敗的原因
異常種類(lèi):
LockedException
賬戶鎖定CredentialsExpiredException
密碼過(guò)期AccountExpiredException
賬戶過(guò)期DisabledException
賬戶被禁止BadCredentialsException
用戶名或者密碼錯(cuò)誤
.failureHandler((req, res, e) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(e.getMessage()); out.flush(); out.close(); })
配置類(lèi)代碼:
package com.scexample.sc.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.io.PrintWriter; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("xiaoming") .password("123456").roles("admin"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個(gè)是用來(lái)忽略一些url地址,對(duì)其不進(jìn)行校驗(yàn),通常用在一些靜態(tài)文件中。 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/aaa.html") .loginProcessingUrl("/logintest") .usernameParameter("name") .passwordParameter("passwd") .successHandler((req, res, authentication) -> { Object principal = authentication.getPrincipal(); res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(new ObjectMapper().writeValueAsString(principal)); out.flush(); out.close(); }) .failureHandler((req, res, e) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(e.getMessage()); out.flush(); out.close(); }) .permitAll() .and() .csrf().disable() } }
未認(rèn)證處理方法
spring security默認(rèn)情況下,如果認(rèn)證不成功,直接重定向到登錄頁(yè)面。
但是項(xiàng)目中,我們有的時(shí)候不需要這樣,我們需要在前端進(jìn)行判斷 ,然后再?zèng)Q定進(jìn)行其他的處理,那我們就可以用authenticationEntryPoint這個(gè)接口進(jìn)行自定義了,取消它的默認(rèn)重定向行為。
該方法有三個(gè)參數(shù)
req
:相當(dāng)與HttpServletRequestres
:相當(dāng)與HttpServletResposeauthException
:指的就是我們未認(rèn)證的exception
.csrf().disable() .exceptionHandling() .authenticationEntryPoint((req, res, authException) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write("檢測(cè)到未登錄狀態(tài),請(qǐng)先登錄"); out.flush(); out.close(); }
配置類(lèi)代碼
package com.scexample.sc.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.io.PrintWriter; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("xiaoming") .password("123456").roles("admin"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個(gè)是用來(lái)忽略一些url地址,對(duì)其不進(jìn)行校驗(yàn),通常用在一些靜態(tài)文件中。 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/aaa.html") .loginProcessingUrl("/logintest") .usernameParameter("name") .passwordParameter("passwd") .successHandler((req, res, authentication) -> { Object principal = authentication.getPrincipal(); res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(new ObjectMapper().writeValueAsString(principal)); out.flush(); out.close(); }) .failureHandler((req, res, e) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(e.getMessage()); out.flush(); out.close(); }) .permitAll() .and() .csrf().disable() .exceptionHandling() .authenticationEntryPoint((req, res, authException) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write("檢測(cè)到未登錄狀態(tài),請(qǐng)先登錄"); out.flush(); out.close(); } ); } }
注銷(xiāo)登錄
.logoutSuccessHandler((req, res, authentication) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write("注銷(xiāo)成功"); out.flush(); out.close(); })
配置類(lèi)代碼:
package com.scexample.sc.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.io.PrintWriter; @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("xiaoming") .password("123456").roles("admin"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/js/**","/css/**","/images/**"); //這個(gè)是用來(lái)忽略一些url地址,對(duì)其不進(jìn)行校驗(yàn),通常用在一些靜態(tài)文件中。 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/aaa.html") .loginProcessingUrl("/logintest") .usernameParameter("name") .passwordParameter("passwd") .successHandler((req, res, authentication) -> { Object principal = authentication.getPrincipal(); res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(new ObjectMapper().writeValueAsString(principal)); out.flush(); out.close(); }) .failureHandler((req, res, e) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write(e.getMessage()); out.flush(); out.close(); }) .permitAll() .and() .logout() .logoutUrl("/logout") .logoutSuccessHandler((req, res, authentication) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write("注銷(xiāo)成功"); out.flush(); out.close(); }) .permitAll() .and() .csrf().disable() .exceptionHandling() .authenticationEntryPoint((req, res, authException) -> { res.setContentType("application/json;charset=utf-8"); PrintWriter out = res.getWriter(); out.write("檢測(cè)到未登錄狀態(tài),請(qǐng)先登錄"); out.flush(); out.close(); } ); } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

詳解SpringBoot啟動(dòng)代碼和自動(dòng)裝配源碼分析

Springboot調(diào)整接口響應(yīng)返回時(shí)長(zhǎng)詳解(解決響應(yīng)超時(shí)問(wèn)題)

基于Java的電梯系統(tǒng)實(shí)現(xiàn)過(guò)程

SpringBoot集成SwaggerUi以及啟動(dòng)時(shí)遇到的錯(cuò)誤

SpringBoot使用Flyway進(jìn)行數(shù)據(jù)庫(kù)遷移的實(shí)現(xiàn)示例

基于XML配置Spring的自動(dòng)裝配過(guò)程解析