Spring Security 异常处理指南:认证与授权失败的自定义处理

1. 概述

本文将介绍如何在 Spring Security 中自定义认证和授权失败的处理方式,包括:

  • 认证成功处理

  • 认证失败处理

  • 授权失败处理

2. 认证结果处理

2.1 认证成功处理

解决方案

自定义类实现 AuthenticationSuccessHandler 接口,重写 onAuthenticationSuccess 方法。

实现步骤
  1. 定义认证成功处理器:

java

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, 
                                      HttpServletResponse httpServletResponse, 
                                      Authentication authentication) throws IOException {
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        
        Map map = new HashMap<>();
        map.put("success", true);
        map.put("message", "认证成功");
        
        String message = new ObjectMapper().writeValueAsString(map);
        PrintWriter out = httpServletResponse.getWriter();
        out.write(message);
        out.flush();
        out.close();
    }
}
  1. 配置处理器:

java

http.formLogin()
    .successHandler(new MyAuthenticationSuccessHandler())
    ...

2.2 认证失败处理

解决方案

自定义类实现 AuthenticationFailureHandler 接口,重写 onAuthenticationFailure 方法。

实现步骤
  1. 定义认证失败处理器:

java

public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, 
                                      HttpServletResponse httpServletResponse, 
                                      AuthenticationException e) throws IOException {
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        
        Map map = new HashMap<>();
        map.put("success", false);
        map.put("message", "认证失败");
        
        String message = new ObjectMapper().writeValueAsString(map);
        httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        PrintWriter out = httpServletResponse.getWriter();
        out.write(message);
        out.flush();
        out.close();
    }
}
  1. 配置处理器:

java

http.formLogin()
    .failureHandler(new MyAuthenticationFailureHandler())
    ...

3. 授权结果处理

3.1 授权失败处理概述

当用户请求受保护资源时,需要进行认证和授权检查。Spring Security 提供了两种处理器来处理授权失败:

  • AuthenticationEntryPoint:处理匿名用户访问无权限资源时的异常

  • AccessDeniedHandler:处理认证过的用户访问无权限资源时的异常

3.2 实现步骤

  1. 定义 AccessDeniedHandler(处理已认证用户):

java

public class DefaultAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, 
                      HttpServletResponse httpServletResponse, 
                      AccessDeniedException e) throws IOException {
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        
        Map map = new HashMap<>();
        map.put("success", false);
        map.put("message", "无访问权限");
        
        String message = new ObjectMapper().writeValueAsString(map);
        PrintWriter out = httpServletResponse.getWriter();
        out.write(message);
        out.flush();
        out.close();
    }
}
  1. 定义 AuthenticationEntryPoint(处理匿名用户):

java

public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest httpServletRequest, 
                        HttpServletResponse httpServletResponse, 
                        AuthenticationException e) throws IOException {
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        
        Map map = new HashMap<>();
        map.put("success", false);
        map.put("message", "拒绝访问:" + e.getMessage());
        
        String message = new ObjectMapper().writeValueAsString(map);
        PrintWriter out = httpServletResponse.getWriter();
        out.write(message);
        out.flush();
        out.close();
    }
}
  1. 配置异常处理器:

java

http.exceptionHandling()
    .accessDeniedHandler(new DefaultAccessDeniedHandler()) // 认证成功但权限检查失败的处理器
    .authenticationEntryPoint(new MyAuthenticationEntryPoint()); // 匿名用户的权限检查失败的处理器

4. 总结

通过自定义 Spring Security 的异常处理器,我们可以:

  1. 统一认证成功/失败的响应格式

  2. 提供更友好的授权失败提示

  3. 实现前后端分离架构下的统一错误处理

这些自定义处理器可以很好地集成到 RESTful API 服务中,提供标准化的错误响应。

你可能感兴趣的:(java,数据库,servlet,Security)