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);
})
效果如下: