SpringSecurity 自定义登陆验证结果处理场景

自定义登陆验证结果处理场景

  • 不同的人登陆之后,看到不同的首页(即向不同页面跳转)
  • 前后端分离的应用,期望相应结果是JSON,而不是html页面

formLogin模式登陆认证无法满足以上需求

在配置文件中自定义logintype变量

spring:
  security:
    logintype: JSON

验证成功Handler

  1. 在config包下创建MyAuthenticationSuccessHandler类,继承SavedRequestAwareAuthenticationSuccessHandler 类
  2. 重写onAuthenticationSuccess方法
  3. 对接受的信息进行判断处理
@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

  1. 在config包下创建MyAuthenticationFailureHandler 类,继承SimpleUrlAuthenticationFailureHandler 类
  2. 重写onAuthenticationFailure方法
  3. 对接受的信息进行判断处理
@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注入

spring 用户名密码非空验证_spring

对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;
  }
}

测试

输入正确的账号密码

spring 用户名密码非空验证_java_02


成功进入首页

spring 用户名密码非空验证_spring 用户名密码非空验证_03


输入错误的账号密码

spring 用户名密码非空验证_spring boot_04


提示错误并返回到登陆页

spring 用户名密码非空验证_spring 用户名密码非空验证_05