【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

相关推荐
开心猴爷21 分钟前
iOS App 性能测试中常被忽略的运行期问题
后端
星辰烈龙25 分钟前
黑马程序员Java基础9
java·开发语言
山沐与山26 分钟前
【Redis】Redis集群模式架构详解
java·redis·架构
ss27337 分钟前
Java并发编程:DelayQueue延迟订单系统
java·python·算法
SHERlocked9339 分钟前
摄像头 RTSP 流视频多路实时监控解决方案实践
c++·后端·音视频开发
wcy_101142 分钟前
七大软件设计原则
java·设计规范
invicinble43 分钟前
jar包在执行的时候需要关注的细节(提供一个解构jvm问题的视角)
java·jvm·jar
麦芽糖02191 小时前
SSE介绍及使用(Server-Send Events)
java
alan07211 小时前
【Java + Elasticsearch全量 & 增量同步实战】
java·elasticsearch·jenkins
AutoMQ1 小时前
How does AutoMQ implement a sub-10ms latency Diskless Kafka?
后端·架构