导读:本期聚焦于小伙伴创作的《如何通过 Spring Security 自定义 Filter 实现 OAuth2 流程中动态权限校验》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何通过 Spring Security 自定义 Filter 实现 OAuth2 流程中动态权限校验》有用,将其分享出去将是对创作者最好的鼓励。

在 Spring Security 整合 OAuth2 的认证授权体系中,默认的权限校验通常基于静态配置或者固定的角色规则,当业务需要根据实时数据、用户属性动态调整权限判断逻辑时,就需要通过自定义 Filter 来扩展权限校验能力。自定义 Filter 可以在 OAuth2 完成令牌校验之后,进入接口方法之前介入请求处理流程,实现灵活的权限判断。

如何通过 Spring Security 自定义 Filter 实现 OAuth2 流程中动态权限校验

自定义 Filter 的实现思路

要实现在 OAuth2 流程中注入动态权限校验,首先需要明确 Filter 的执行时机。OAuth2 的令牌校验由 Spring Security 内置的 OAuth2 相关 Filter 完成,我们的自定义 Filter 需要放在这些 Filter 之后执行,这样才能获取到已经解析完成的用户认证信息,再基于这些信息做动态权限判断。

核心实现步骤

  • 创建实现 jakarta.servlet.Filter 接口的自定义 Filter 类
  • 在 Filter 中获取当前请求的 OAuth2 认证信息,提取用户标识、角色等基础数据
  • 调用动态权限规则获取接口,查询当前请求路径对应的权限要求
  • 对比用户权限与规则要求,不满足则直接返回无权限响应
  • 将自定义 Filter 注册到 Spring Security 的 Filter 链中,指定正确的执行顺序

自定义 Filter 代码实现

以下是一个基础的自定义动态权限校验 Filter 实现示例,代码基于 Spring Security 6 和 Jakarta Servlet 规范:

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

public class DynamicPermissionFilter implements Filter {

    // 动态权限规则获取接口,实际业务中可替换为数据库、配置中心等实现
    private final DynamicPermissionService permissionService;

    public DynamicPermissionFilter(DynamicPermissionService permissionService) {
        this.permissionService = permissionService;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 获取当前请求的认证信息,OAuth2 流程中会解析为 JwtAuthenticationToken
        Authentication authentication = (Authentication) request.getUserPrincipal();
        // 如果未认证,直接放行给后续 Filter 处理,避免重复校验
        if (authentication == null || !authentication.isAuthenticated()) {
            filterChain.doFilter(request, response);
            return;
        }

        // 提取当前请求的路径和方法
        String requestUri = request.getRequestURI();
        String requestMethod = request.getMethod();

        // 获取当前用户的所有权限标识
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        List<String> userPermissions = authorities.stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList());

        // 如果是 JWT 认证,还可以从 JWT 中提取自定义字段,比如用户ID、部门等信息
        String userId = null;
        if (authentication instanceof JwtAuthenticationToken jwtAuth) {
            userId = jwtAuth.getToken().getClaimAsString("user_id");
        }

        // 调用动态权限服务,判断当前用户是否有访问当前接口的权限
        boolean hasPermission = permissionService.checkPermission(userId, userPermissions, requestUri, requestMethod);
        if (!hasPermission) {
            // 无权限时返回 403 状态码和提示信息
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{"code":403,"msg":"无访问权限"}");
            return;
        }

        // 权限校验通过,继续执行后续流程
        filterChain.doFilter(request, response);
    }
}

动态权限服务接口定义

上面的 Filter 依赖动态权限服务来获取权限规则,以下是该服务的基础接口定义,开发者可以根据实际业务实现具体的逻辑:

import java.util.List;

public interface DynamicPermissionService {

    /**
     * 校验用户是否有访问指定接口的权限
     * @param userId 用户ID,可为空
     * @param userPermissions 用户已有的权限标识列表
     * @param requestUri 请求路径
     * @param requestMethod 请求方法
     * @return 是否有权限
     */
    boolean checkPermission(String userId, List<String> userPermissions, String requestUri, String requestMethod);
}

将自定义 Filter 注册到 Spring Security

实现 Filter 之后,需要将其注册到 Spring Security 的 Filter 链中,并且要保证它在 OAuth2 令牌校验 Filter 之后执行。可以通过 SecurityFilterChain 来配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig {

    private final DynamicPermissionService dynamicPermissionService;

    public SecurityConfig(DynamicPermissionService dynamicPermissionService) {
        this.dynamicPermissionService = dynamicPermissionService;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 创建自定义 Filter 实例
        DynamicPermissionFilter dynamicPermissionFilter = new DynamicPermissionFilter(dynamicPermissionService);

        http
            // OAuth2 资源服务器配置
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())))
            // 配置自定义 Filter,放在 UsernamePasswordAuthenticationFilter 之后,确保认证信息已经解析完成
            .addFilterAfter(dynamicPermissionFilter, UsernamePasswordAuthenticationFilter.class)
            // 其他安全配置
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            );

        return http.build();
    }

    // JWT 认证转换器,用于提取 JWT 中的权限信息
    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter authoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // 设置 JWT 中权限字段的 key,默认是 scope,可根据实际调整
        authoritiesConverter.setAuthorityPrefix("");
        authoritiesConverter.setAuthoritiesClaimName("permissions");

        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
        return converter;
    }
}

注意事项

  • 自定义 Filter 的执行顺序非常重要,如果放在 OAuth2 令牌校验 Filter 之前,会无法获取到正确的认证信息,导致校验逻辑失效。
  • 动态权限规则的实现需要考虑性能问题,高频访问的接口权限规则建议做缓存,避免每次请求都查询数据库或者配置中心。
  • 对于不需要权限校验的公开接口,需要在 Filter 中做白名单处理,或者在 Spring Security 的 authorizeHttpRequests 中提前放行,避免不必要的校验。
  • 如果系统中同时存在多种认证方式,需要在 Filter 中做好认证类型的判断,避免非 OAuth2 认证请求出现异常。

常见问题排查

如果自定义 Filter 没有生效,可以先检查 Filter 的注册顺序是否正确,通过调试查看 Filter 的 doFilter 方法是否被调用。如果获取不到认证信息,大概率是 Filter 执行时机过早,需要调整 addFilterAfter 的参数,确保在 OAuth2 相关的认证 Filter 之后执行。如果权限校验逻辑不符合预期,可以先打印出用户权限列表和请求的路径、方法信息,对比动态权限规则的实现是否有问题。

Spring_SecurityOAuth2自定义Filter动态权限校验修改时间:2026-07-04 20:45:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。