【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 分钟前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
豪宇刘1 小时前
MyBatis的面试题以及详细解答二
java·servlet·tomcat
秋恬意1 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
刘大辉在路上2 小时前
突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除
git·后端·gitlab·版本管理·源代码管理
FF在路上2 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进2 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
众拾达人3 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.3 小时前
Mybatis-Plus
java·开发语言
不良人天码星3 小时前
lombok插件不生效
java·开发语言·intellij-idea
守护者1703 小时前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习