successHandler
onAuthenticationSuccess里的第一个参数是当前请求对象,第二个是响应对象,第三个是验证成功的用户信息
小技巧:ALT+enter生成lambda表达式
我们准备一个ResBean
package org.ikun.security_demo.model; public class ResBean { private Integer status; private String msg; private Object data; public static ResBean ok(String msg,Object data){ return new ResBean(200,msg,data); } public static ResBean ok(String msg){ return new ResBean(200,msg,null); } public static ResBean error(String msg,Object data){ return new ResBean(204,msg,data); } public static ResBean error(String msg){ return new ResBean(204,msg,null); } private ResBean(){ } private ResBean(Integer status, String msg, Object data) { this.status = status; this.msg = msg; this.data = data; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } }
Security里的代码
package org.ikun.security_demo; import com.fasterxml.jackson.databind.ObjectMapper; import org.ikun.security_demo.model.ResBean; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration @EnableWebSecurity public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //开始认证 //设置登录,注销,表单登录不用拦截,其他请求要拦截 http.authorizeRequests().antMatchers("/","/login.html").anonymous() //所有的请求,类似于shiro中的 /** .anyRequest() //必须要认证之后才能访问,类似于shiro的authc .authenticated() .and() //开始配置登录表单 .formLogin() //配置登录页面,如果访问了一个需要登录以后才能访问的页面,那么就会自动登录到这个页面 .loginPage("/login.html") //配置处理登录请求的接口,其实就是配置了过滤器里的拦截规则,将来的登录请求就会在过滤器中被处理 .loginProcessingUrl("/doLogin") //配置登录表单中用户名的 key .usernameParameter("username") //配置登录表单中的密码 默认也是username 和 password .passwordParameter("password") //配置登录成功后访问的接口 // .defaultSuccessUrl("/hello") //登录失败后访问的接口 //.failureUrl("/login.html") //登录成功处理器 .successHandler((request, response, authentication) -> { response.setContentType("application/json;charset=utf-8"); ResBean resBean = ResBean.ok("登陆成功", authentication.getPrincipal());//getPrincipal()就是你的用户对象 String s = new ObjectMapper().writeValueAsString(resBean); response.getWriter().write(s); }) //关闭默认的csrf认证 .and().csrf().disable(); } }
登陆成功后,返回结果如下
登录失败的回调亦然。failureHandler
package org.ikun.security_demo; import com.fasterxml.jackson.databind.ObjectMapper; import org.ikun.security_demo.model.ResBean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.*; 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.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration @EnableWebSecurity public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //开始认证 //设置登录,注销,表单登录不用拦截,其他请求要拦截 http.authorizeRequests().antMatchers("/","/login.html").anonymous() //所有的请求,类似于shiro中的 /** .anyRequest() //必须要认证之后才能访问,类似于shiro的authc .authenticated() .and() //开始配置登录表单 .formLogin() //配置登录页面,如果访问了一个需要登录以后才能访问的页面,那么就会自动登录到这个页面 .loginPage("/login.html") //配置处理登录请求的接口,其实就是配置了过滤器里的拦截规则,将来的登录请求就会在过滤器中被处理 .loginProcessingUrl("/doLogin") //配置登录表单中用户名的 key .usernameParameter("username") //配置登录表单中的密码 默认也是username 和 password .passwordParameter("password") //配置登录成功后访问的接口 // .defaultSuccessUrl("/hello") //登录失败后访问的接口 //.failureUrl("/login.html") //登录成功处理器 .successHandler((request, response, authentication) -> { response.setContentType("application/json;charset=utf-8"); ResBean resBean = ResBean.ok("登陆成功", authentication.getPrincipal());//getPrincipal()就是你的用户对象 String s = new ObjectMapper().writeValueAsString(resBean); response.getWriter().write(s); }) .failureHandler((request, response, exception) -> { //登录失败可能有很多种原因 response.setContentType("application/json;charset=utf-8"); ResBean resBean = ResBean.ok("登陆失败"); if (exception instanceof BadCredentialsException){ resBean.setMsg("用户名或密码输入错误,登录失败"); }else if (exception instanceof UsernameNotFoundException){ //这个异常默认隐藏了,所以这个分支不会进来,怕有人试密码 }else if (exception instanceof LockedException){ resBean.setMsg("账户被锁定,登录失败"); }else if (exception instanceof AccountExpiredException){ resBean.setMsg("账户过期,登录失败"); }else if (exception instanceof CredentialsExpiredException){ resBean.setMsg("密码过期,登录失败"); }else if (exception instanceof DisabledException){ resBean.setMsg("账户被禁用,登录失败"); } String s = new ObjectMapper().writeValueAsString(resBean); response.getWriter().write(s); }) //关闭默认的csrf认证 .and().csrf().disable(); } }
我们看一下效果
ok没问题
最后介绍一个exceptionHandling
用户未登录就访问某一个页面,就会触发这个方法
.exceptionHandling() //用户未登录就访问某一个页面,就会触发这个方法 .authenticationEntryPoint((request, response, authException) -> { response.setContentType("application/json;charset=utf-8"); ResBean resBean = ResBean.error("尚未登录,请登录"); String s = new ObjectMapper().writeValueAsString(resBean); response.getWriter().write(s); })
效果如下: