Spring Security中successHandler和failureHandler使用方式
前言
successHandler和failureHandler是Spring Security中兩個(gè)較為強(qiáng)大的用來處理登錄成功和失敗的回調(diào)函數(shù),通過它們兩個(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();
})配置類代碼
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è)是用來忽略一些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:這里保存了我們登錄失敗的原因
異常種類:
LockedException賬戶鎖定CredentialsExpiredException密碼過期AccountExpiredException賬戶過期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();
})配置類代碼:
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è)是用來忽略一些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();
}配置類代碼
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è)是用來忽略一些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();
}
);
}
}

注銷登錄
.logoutSuccessHandler((req, res, authentication) -> {
res.setContentType("application/json;charset=utf-8");
PrintWriter out = res.getWriter();
out.write("注銷成功");
out.flush();
out.close();
})配置類代碼:
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è)是用來忽略一些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("注銷成功");
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è)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java 使用IO流實(shí)現(xiàn)大文件的分割與合并實(shí)例詳解
這篇文章主要介紹了Java 使用IO流實(shí)現(xiàn)大文件的分割與合并實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12
手動(dòng)實(shí)現(xiàn)將本地jar添加到Maven倉(cāng)庫(kù)
這篇文章主要介紹了手動(dòng)實(shí)現(xiàn)將本地jar添加到Maven倉(cāng)庫(kù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
詳解使用@RequestBody取POST方式的json字符串
這篇文章主要介紹了詳解使用@RequestBody取POST方式的json字符串,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
Java計(jì)算兩個(gè)時(shí)間相差的秒數(shù)怎么算
這篇文章主要介紹了Java計(jì)算兩個(gè)時(shí)間相差的秒數(shù),通過實(shí)例代碼補(bǔ)充介紹了Java 獲取兩個(gè)時(shí)間的時(shí)間差(時(shí)、分、秒)問題,感興趣的朋友跟隨小編一起看看吧2024-03-03
SpringBoot中Date格式化處理的三種實(shí)現(xiàn)
Spring Boot作為一個(gè)簡(jiǎn)化Spring應(yīng)用開發(fā)的框架,提供了多種處理日期格式化的方法,本文主要介紹了SpringBoot中Date格式化處理實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03

