Spring Security中successHandler和failureHandler使用方式
作者:放肆热爱
这篇文章主要介绍了Spring Security中successHandler和failureHandler使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
前言
successHandler和failureHandler是Spring Security中两个较为强大的用来处理登录成功和失败的回调函数,通过它们两个我们就可以自定义一些前后端数据的交互。
successHandler
该方法有三个参数
req
:相当与HttpServletRequestres
:相当与HttpServletResposeauthentication
:这里保存了我们登录后的用户信息
进行如下配置
.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/**"); //这个是用来忽略一些url地址,对其不进行校验,通常用在一些静态文件中。 } @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
该方法有三个参数
req
:相当与HttpServletRequestres
:相当与HttpServletResposee
:这里保存了我们登录失败的原因
异常种类:
LockedException
账户锁定CredentialsExpiredException
密码过期AccountExpiredException
账户过期DisabledException
账户被禁止BadCredentialsException
用户名或者密码错误
.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/**"); //这个是用来忽略一些url地址,对其不进行校验,通常用在一些静态文件中。 } @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() } }
未认证处理方法
spring security默认情况下,如果认证不成功,直接重定向到登录页面。
但是项目中,我们有的时候不需要这样,我们需要在前端进行判断 ,然后再决定进行其他的处理,那我们就可以用authenticationEntryPoint这个接口进行自定义了,取消它的默认重定向行为。
该方法有三个参数
req
:相当与HttpServletRequestres
:相当与HttpServletResposeauthException
:指的就是我们未认证的exception
.csrf().disable() .exceptionHandling() .authenticationEntryPoint((req, res, authException) -> { 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/**"); //这个是用来忽略一些url地址,对其不进行校验,通常用在一些静态文件中。 } @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("检测到未登录状态,请先登录"); 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/**"); //这个是用来忽略一些url地址,对其不进行校验,通常用在一些静态文件中。 } @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("检测到未登录状态,请先登录"); out.flush(); out.close(); } ); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。