• (新)Spring Security如何自定义失败处理器


    (直接从三、实战开始看)

    (直接从三、实战开始看)

    (直接从三、实战开始看)可点击:

    (新)Spring Security如何自定义失败处理器-CSDN博客

    我们还希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json,这样可以让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制。

    在SpringSecurity中,如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。

    如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理

    如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。

    所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置SpringSecurity即可。


    在Spring Security中,你可以通过实现特定的接口来自定义认证失败处理器(AuthenticationFailureHandler)和授权失败处理器(AccessDeniedHandler)。以下是如何分别自定义它们的步骤:

    一、自定义认证失败处理器(AuthenticationFailureHandler)

    1.1创建自定义的AuthenticationFailureHandler

    1. import javax.servlet.http.HttpServletRequest;
    2. import javax.servlet.http.HttpServletResponse;
    3. import org.springframework.security.core.AuthenticationException;
    4. import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    5. public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
    6. @Override
    7. public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
    8. AuthenticationException exception) throws IOException, ServletException {
    9. // 在这里处理认证失败的情况
    10. response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    11. response.getWriter().write("登录失败: " + exception.getMessage());
    12. }
    13. }

    1.2在Spring Security配置中使用你的自定义认证失败处理器

    1. @Override
    2. protected void configure(HttpSecurity http) throws Exception {
    3. http
    4. // ... 其他配置 ...
    5. .formLogin()
    6. .failureHandler(new CustomAuthenticationFailureHandler()) // 设置自定义认证失败处理器
    7. // ... 其他表单登录配置 ...
    8. // ... 其他HTTP安全配置 ...
    9. ;
    10. }

    二、自定义授权失败处理器(AccessDeniedHandler)

    2.1创建自定义的AccessDeniedHandler

    1. import javax.servlet.http.HttpServletRequest;
    2. import javax.servlet.http.HttpServletResponse;
    3. import org.springframework.security.access.AccessDeniedException;
    4. import org.springframework.security.web.access.AccessDeniedHandler;
    5. public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    6. @Override
    7. public void handle(HttpServletRequest request, HttpServletResponse response,
    8. AccessDeniedException accessDeniedException) throws IOException, ServletException {
    9. // 在这里处理授权失败的情况
    10. response.setStatus(HttpServletResponse.SC_FORBIDDEN);
    11. response.getWriter().write("权限不足: " + accessDeniedException.getMessage());
    12. }
    13. }

    2.2在Spring Security配置中使用你的自定义授权失败处理器

    1. @Override
    2. protected void configure(HttpSecurity http) throws Exception {
    3. http
    4. // ... 其他配置 ...
    5. .exceptionHandling()
    6. .accessDeniedHandler(new CustomAccessDeniedHandler()) // 设置自定义授权失败处理器
    7. // ... 其他异常处理配置 ...
    8. // ... 其他HTTP安全配置 ...
    9. ;
    10. }

    三、实战

    我们还希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json,这样可以让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制

    在SpringSecurity中,如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。

    如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。

    如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。

    所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置SpringSecurity即可。

    (com.sangeng.handler)

    自定义认证失败处理器:

    1. @Component
    2. public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
    3. @Override
    4. public void commence(HttpServletRequest request, HttpServletResponse
    5. response, AuthenticationException authException) throws IOException,
    6. ServletException {
    7. ResponseResult result = new
    8. ResponseResult(HttpStatus.UNAUTHORIZED.value(), "认证失败请重新登录");
    9. String json = JSON.toJSONString(result);
    10. WebUtils.renderString(response, json);
    11. }
    12. }

    自定义授权失败处理器:

    1. @Component
    2. public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
    3. @Override
    4. public void handle(HttpServletRequest request, HttpServletResponse response,
    5. AccessDeniedException accessDeniedException) throws IOException,
    6. ServletException {
    7. ResponseResult result = new ResponseResult(HttpStatus.FORBIDDEN.value(),
    8. "权限不足");
    9. String json = JSON.toJSONString(result);
    10. WebUtils.renderString(response, json);
    11. }
    12. }

    修改配置类:

    1. @Configuration //配置类
    2. @EnableWebSecurity // 开启Spring Security的功能 代替了 implements WebSecurityConfigurerAdapter
    3. public class SecurityConfig {
    4. @Autowired
    5. AuthenticationConfiguration authenticationConfiguration;//获取AuthenticationManager
    6. @Autowired
    7. JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    8. @Autowired
    9. AccessDeniedHandlerImpl accessDeniedHandler;
    10. @Autowired
    11. AuthenticationEntryPointImpl authenticationEntryPoint;
    12. @Bean
    13. public PasswordEncoder passwordEncoder() {
    14. return new BCryptPasswordEncoder();
    15. }
    16. @Bean
    17. public AuthenticationManager authenticationManagerBean() throws Exception {
    18. return authenticationConfiguration.getAuthenticationManager();
    19. }
    20. /**
    21. * 配置Spring Security的过滤链。
    22. *
    23. * @param http 用于构建安全配置的HttpSecurity对象。
    24. * @return 返回配置好的SecurityFilterChain对象。
    25. * @throws Exception 如果配置过程中发生错误,则抛出异常。
    26. */
    27. @Bean
    28. SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    29. http
    30. // 禁用CSRF保护
    31. .csrf(csrf -> csrf.disable())
    32. // 设置会话创建策略为无状态
    33. .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
    34. // 配置授权规则 指定user/login路径.允许匿名访问(未登录可访问已登陆不能访问). 其他路径需要身份认证
    35. .authorizeHttpRequests(auth -> auth.requestMatchers("/user/login").anonymous().anyRequest().authenticated())
    36. //开启跨域访问
    37. .cors(AbstractHttpConfigurer::disable)
    38. // 添加JWT认证过滤器
    39. .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
    40. // 配置异常处理
    41. .exceptionHandling(exception -> exception.accessDeniedHandler(accessDeniedHandler).authenticationEntryPoint(authenticationEntryPoint));
    42. // 构建并返回安全过滤链
    43. return http.build();
    44. }

    注意事项

    • 确保你的认证和授权失败处理器都正确实现了相应的接口,并且正确设置了它们的状态码和响应内容。
    • 你可以将你的自定义处理器作为Spring Bean注入到你的配置中,而不是直接在配置方法中创建新的实例。这样可以更好地管理你的Spring应用程序中的bean。
    • 在处理认证和授权失败时,你可能希望返回JSON而不是纯文本响应,特别是在构建RESTful API时。为此,你可以使用@ResponseBody注解或ResponseEntity类来构建JSON响应。

  • 相关阅读:
    《研发效能(DevOps)工程师》课程简介(三)丨IDCF
    反斜杠,让您的csv文档字符不撞车;让“借”您csv数据的人叫苦不迭。
    【Unity入门计划】2D游戏中遮挡问题的处理方法&伪透视
    SpringBoot Actuator未授权访问漏洞修复
    89:第七章:开发前台首页、作家个人展示页、粉丝等功能:10:【前台,作家中心:粉丝比例柱状图、饼状图;粉丝地域分布】(前端图表使用Echarts实现;)
    Python时间序列分析库介绍:statsmodels、tslearn、tssearch、tsfresh
    图解LeetCode——754. 到达终点数字(难度:中等)
    快速上手Linux核心命令(六):Linux的文本编辑器vi和vim
    软件性能瓶颈问题之数据库性能问题定位
    [Qt]QListView 重绘实例之一:背景重绘
  • 原文地址:https://blog.csdn.net/weixin_55772633/article/details/139899727