【Spring Security】AccessDeniedHandler 用户无权限操作接口时处理

文章目录

前言

AccessDeniedHandler 接口负责处理用户在没有足够权限访问某资源时的行为。当用户尝试访问他们没有权限的资源时,这个处理器被触发。

官方是给了几个默认的处理器,当然,我们也可以自己自定义处理器,那么先简单介绍一下官方的处理器,然后再自己写一个自定义处理器。

官方给的处理器

AccessDeniedHandlerImpl

当用户访问一个无权限访问的接口时,触发的处理器。

AccessDeniedHandlerImpl 中可以设置一个重定向的路径,其中 AccessDeniedHandlerImpl 中还会返回一个 403 的状态码。

java 复制代码
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);

        http
                // 退出登录
                .exceptionHandling()
                // 无权限访问资源处理器
                .accessDeniedHandler(accessDeniedHandler());
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
        // 设置重定向的错误页面
        accessDeniedHandler.setErrorPage("/access-denied");
        return accessDeniedHandler;
    }

InvalidSessionAccessDeniedHandler

InvalidSessionAccessDeniedHandler 是当用户的会话时间到期后,执行的处理器。

java 复制代码
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);

        http
                // 退出登录
                .exceptionHandling()
                // 无权限访问资源处理器
                .accessDeniedHandler(accessDeniedHandler());
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
    	// 会话时间到期后执行的处理器
        return new InvalidSessionAccessDeniedHandler(invalidSessionStrategy());
    }

    @Bean
    public InvalidSessionStrategy invalidSessionStrategy() {
        // 使用 SimpleRedirectInvalidSessionStrategy 或自定义实现
        return new SimpleRedirectInvalidSessionStrategy("/session-invalid");
    }

RequestMatcherDelegatingAccessDeniedHandler

RequestMatcherDelegatingAccessDeniedHandler 是用来灵活处理不同类型请求的访问拒绝逻辑,比如URL模式、HTTP方法等。

java 复制代码
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);

        http
                // 退出登录
                .exceptionHandling()
                // 无权限访问资源处理器
                .accessDeniedHandler(accessDeniedHandler());
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        LinkedHashMap<RequestMatcher, AccessDeniedHandler> handlerMap = new LinkedHashMap<>();

        AccessDeniedHandlerImpl userAccessDeniedHandler = new AccessDeniedHandlerImpl();
        // 设置重定向的错误页面
        userAccessDeniedHandler.setErrorPage("/user-access-denied");
        handlerMap.put(new AntPathRequestMatcher("/user/**"), userAccessDeniedHandler);

        RequestMatcherDelegatingAccessDeniedHandler accessDeniedHandler = new RequestMatcherDelegatingAccessDeniedHandler(
                handlerMap,
                // 默认的执行处理器
                new AccessDeniedHandlerImpl());
        return accessDeniedHandler;
    }

DelegatingAccessDeniedHandler

DelegatingAccessDeniedHandler 是根据你出现权限访问错误后,根据出现的错误进行设置规则。

java 复制代码
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);

        http
                // 退出登录
                .exceptionHandling()
                // 无权限访问资源处理器
                .accessDeniedHandler(accessDeniedHandler());
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers = new LinkedHashMap<>();
        // 出现 AuthorizationServiceException 时执行
        handlers.put(AuthorizationServiceException.class, new AccessDeniedHandlerImpl());
        // 出现 MissingCsrfTokenException 时执行
        handlers.put(MissingCsrfTokenException.class, new AccessDeniedHandlerImpl());

        return new DelegatingAccessDeniedHandler(
                handlers,
                // 默认执行的处理方式
                new AccessDeniedHandlerImpl());
    }

自定义处理器

java 复制代码
package com.security.handler.access;

import com.alibaba.fastjson2.JSON;
import com.security.controller.vo.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@Slf4j
public class CustomAccessDeniedHandlerImpl implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        log.info("CustomAccessDeniedHandlerImpl 授权失败处理 ...");
        /**
         * 设置响应状态值
         */
        response.setStatus(403);
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        String json = JSON.toJSONString(
                ResponseResult.builder()
                        .code(403)
                        .message("认证失败!")
                        .build());

        // JSON信息
        response.getWriter().println(json);
    }

}
java 复制代码
package com.security.config;

import com.security.handler.access.CustomAccessDeniedHandlerImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.cors.CorsConfiguration;



@Configuration
@EnableWebSecurity
// 开启限制访问资源所需权限
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfigurationTest extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);

        http
                // 退出登录
                .exceptionHandling()
                // 无权限访问资源处理器
                .accessDeniedHandler(accessDeniedHandler());
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandlerImpl();
    }


}

End

相关推荐
wangbing112523 分钟前
springboot应用关闭时触发动作
java·spring boot·后端
weixin_460443563 小时前
2026年新修订《网络安全法》实施:Java私有化考试系统如何做好SBOM、漏洞治理与安全升级?
java·开发语言·在线考试系统·企业培训考试系统·宏远培训考试系统·国企培训考试系统·国产化培训系统
子兮曰4 小时前
把 649 种文件格式塞进一个网页里:一个「文件不出浏览器」的预览器
前端·javascript·后端
海鸥-w6 小时前
什么是AOP
java
java资料站7 小时前
十一、Spring AI Alibaba · 高级 · 多智能体(Multi-agent)
人工智能·spring·microsoft
全栈弄潮儿7 小时前
Python实战第2期: 变量与数据类型
后端·python·agent
Cc.Y7 小时前
Java零基础入门:可变字符串与包装类:StringBuilder、StringBuffer 与 通讯录管理系统实战
java·开发语言·python
paopaokaka_luck7 小时前
基于springboot+vue的智慧家政管理系统(AI问答、 WebSocket实时沟通、ECharts运营分析、订单规则与服务追踪)
java·javascript·spring boot·数据分析·echarts·mybatis
sm_926787057 小时前
RFID 标签打印的技术实现要点与二次开发实践
java·大数据·前端·c++·编辑器