SpringSecurity 自定义登陆验证结果处理场景
自定义登陆验证结果处理场景
- 不同的人登陆之后,看到不同的首页(即向不同页面跳转)
- 前后端分离的应用,期望相应结果是JSON,而不是html页面
formLogin模式登陆认证无法满足以上需求
在配置文件中自定义logintype变量
spring:
security:
logintype: JSON
验证成功Handler
- 在config包下创建MyAuthenticationSuccessHandler类,继承SavedRequestAwareAuthenticationSuccessHandler 类
- 重写onAuthenticationSuccess方法
- 对接受的信息进行判断处理
@Component
public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Value("${spring.security.logintype}")
private String loginType;
private static ObjectMapper objectMapper = new ObjectMapper(); //SpringBoot自带的把JSON转换为字符串的
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws ServletException, IOException {
if (loginType.equalsIgnoreCase("JSON")){
//如果接受的是JSON数据,则将JSON写回给客户端
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(AjaxResponse.success()));
}else {
//会帮我们跳转到上一次请求的页面
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
验证失败Handler
- 在config包下创建MyAuthenticationFailureHandler 类,继承SimpleUrlAuthenticationFailureHandler 类
- 重写onAuthenticationFailure方法
- 对接受的信息进行判断处理
@Component
public class MyAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
//在application配置文件中配置登陆的类型是JSON数据响应还是做页面响应
@Value("${spring.security.logintype}")
private String loginType;
private static ObjectMapper objectMapper = new ObjectMapper(); //SpringBoot自带的把JSON转换为字符串的工具
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
if (loginType.equalsIgnoreCase("JSON")){
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(
AjaxResponse.userInputError("请检查您的用户名和密码输入是否正确")
));
}else {
response.setContentType("text/html;charset=UTF-8");
super.onAuthenticationFailure(request, response, exception);
}
}
}
在SecurityConfig配置类中讲验证成功和失败的Hander注入
对login表单进行改造
<script type="text/javascript">
function login() {
var username = $("#username").val();
var password = $("#password").val();
if (username === "" || password === ""){
alert('用户名或密码不能为空');
return;
}
$.ajax({
type: "POST",
url: "/login",
data: {
"username": username, //这里的参数名称要和Spring Security配置一致
"password": password
},
success: function (json) {
if(json.isok){
location.href = '/'; //index.html
}else {
alert(json.message);
location.href = '/login.html';
}
},
error: function (e) {
}
});
}
</script>
注:
AjaxResponse是自己创建的返回的前端的类
@Data
public class AjaxResponse {
private boolean isok; //请求是否处理成功
private int code; //请求响应状态码(200、400、500)
private String message; //请求结果描述信息
private Object data; //请求结果数据(通常用于查询操作)
private AjaxResponse(){}
//请求出现异常时的响应数据封装
public static AjaxResponse error(CustomException e) {
AjaxResponse resultBean = new AjaxResponse();
resultBean.setIsok(false);
resultBean.setCode(e.getCode());
resultBean.setMessage(e.getMessage());
return resultBean;
}
//请求出现异常时的响应数据封装
public static AjaxResponse error(CustomExceptionType customExceptionType,
String errorMessage) {
AjaxResponse resultBean = new AjaxResponse();
resultBean.setIsok(false);
resultBean.setCode(customExceptionType.getCode());
resultBean.setMessage(errorMessage);
return resultBean;
}
//请求出现异常时的响应数据封装
public static AjaxResponse userInputError(String errorMessage){
AjaxResponse resultBean = new AjaxResponse();
resultBean.setIsok(false);
resultBean.setCode(CustomExceptionType.USER_INPUT_ERROR.getCode());
resultBean.setMessage(errorMessage);
return resultBean;
}
//请求成功的响应,不带查询数据(用于删除、修改、新增接口)
public static AjaxResponse success(){
AjaxResponse ajaxResponse = new AjaxResponse();
ajaxResponse.setIsok(true);
ajaxResponse.setCode(200);
ajaxResponse.setMessage("请求响应成功!");
return ajaxResponse;
}
//请求成功的响应,带有查询数据(用于数据查询接口)
public static AjaxResponse success(Object obj){
AjaxResponse ajaxResponse = new AjaxResponse();
ajaxResponse.setIsok(true);
ajaxResponse.setCode(200);
ajaxResponse.setMessage("请求响应成功!");
ajaxResponse.setData(obj);
return ajaxResponse;
}
//请求成功的响应,带有查询数据(用于数据查询接口)
public static AjaxResponse success(Object obj,String message){
AjaxResponse ajaxResponse = new AjaxResponse();
ajaxResponse.setIsok(true);
ajaxResponse.setCode(200);
ajaxResponse.setMessage(message);
ajaxResponse.setData(obj);
return ajaxResponse;
}
}
测试
输入正确的账号密码
成功进入首页
输入错误的账号密码
提示错误并返回到登陆页