【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

相关推荐
蜗牛^^O^40 分钟前
Docker和K8S
java·docker·kubernetes
从心归零1 小时前
sshj使用代理连接服务器
java·服务器·sshj
一个诺诺前行的后端程序员2 小时前
springcloud微服务实战<1>
spring·spring cloud·微服务
IT毕设梦工厂2 小时前
计算机毕业设计选题推荐-在线拍卖系统-Java/Python项目实战
java·spring boot·python·django·毕业设计·源码·课程设计
Ylucius3 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
凡人的AI工具箱3 小时前
AI教你学Python 第11天 : 局部变量与全局变量
开发语言·人工智能·后端·python
是店小二呀3 小时前
【C++】C++ STL探索:Priority Queue与仿函数的深入解析
开发语言·c++·后端
七夜zippoe3 小时前
分布式系统实战经验
java·分布式
canonical_entropy3 小时前
金蝶云苍穹的Extension与Nop平台的Delta的区别
后端·低代码·架构
是梦终空3 小时前
JAVA毕业设计176—基于Java+Springboot+vue3的交通旅游订票管理系统(源代码+数据库)
java·spring boot·vue·毕业设计·课程设计·源代码·交通订票