0

0

Spring Security:为特定URL模式配置JWT过滤器

花韻仙語

花韻仙語

发布时间:2025-07-08 19:22:02

|

217人浏览过

|

来源于php中文网

原创

Spring Security:为特定URL模式配置JWT过滤器

本教程详细讲解如何在Spring Boot Security中,精确控制JWT(JSON Web Token)过滤器的应用范围,使其仅作用于指定的URL模式,而非全局生效。通过继承AbstractAuthenticationProcessingFilter并结合RequestMatcher接口,开发者可以灵活定义哪些请求路径需要JWT认证,从而优化安全策略,避免不必要的性能开销,并增强应用的模块化安全性。文章将提供详细的代码示例和配置步骤,帮助读者实现定制化的安全过滤逻辑。

spring security中,我们经常需要自定义过滤器来处理特定的认证或授权逻辑,例如jwt认证。然而,默认情况下,通过httpsecurity.addfilterbefore()或addfilterat()添加的过滤器会作用于所有进来的http请求。对于jwt认证而言,通常我们只希望它对受保护的api路径(例如/api/**)生效,而对静态资源、登录页面或公共接口则无需进行jwt验证。本文将介绍如何利用spring security提供的abstractauthenticationprocessingfilter和requestmatcher接口,实现jwt过滤器的精确控制。

挑战:全局过滤器与局部需求

当我们将一个自定义JWT过滤器(例如CustomJwtAuthenticationFilter)通过以下方式添加到安全链中时:

http.addFilterBefore(customJwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

这个customJwtAuthenticationFilter将会在UsernamePasswordAuthenticationFilter之前,对所有进入应用的请求进行处理。这意味着即使是访问/login、/或任何非API路径,该过滤器也会被触发,这不仅可能导致不必要的性能开销,还可能在某些情况下抛出异常(例如,尝试从没有JWT的请求头中解析令牌)。

解决方案:AbstractAuthenticationProcessingFilter与RequestMatcher

Spring Security提供了一个抽象类AbstractAuthenticationProcessingFilter,它专门用于处理基于请求匹配的认证流程。这个类的核心在于其构造函数可以接收一个RequestMatcher对象。当一个请求到达时,AbstractAuthenticationProcessingFilter会首先调用其内部的RequestMatcher的matches()方法。只有当matches()方法返回true时,过滤器才会继续执行其认证逻辑(即调用attemptAuthentication()方法);否则,它会直接跳过认证过程,将请求传递给安全链中的下一个过滤器。

RequestMatcher是一个接口,它定义了如何根据HttpServletRequest来判断一个请求是否匹配特定条件。Spring Security提供了多种RequestMatcher的实现,其中最常用的是:

  • AntPathRequestMatcher:基于Ant风格路径模式匹配URL。
  • OrRequestMatcher:将多个RequestMatcher组合,只要有一个匹配就返回true。
  • AndRequestMatcher:将多个RequestMatcher组合,只有所有都匹配才返回true。
  • NegatedRequestMatcher:对另一个RequestMatcher的结果取反。

实现步骤

我们将通过以下步骤实现JWT过滤器的精确控制:

Pi智能演示文档
Pi智能演示文档

领先的AI PPT生成工具

下载

1. 改造 CustomJwtAuthenticationFilter

让你的JWT认证过滤器继承AbstractAuthenticationProcessingFilter,并在构造函数中接收RequestMatcher和AuthenticationManager。

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;

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

/**
 * 自定义JWT认证过滤器,仅对匹配特定RequestMatcher的请求进行处理。
 */
public class CustomJwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    /**
     * 构造函数。
     * @param requiresAuthenticationRequestMatcher 定义哪些请求需要此过滤器处理的RequestMatcher
     * @param authenticationManager 认证管理器,用于执行认证逻辑
     */
    public CustomJwtAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher, AuthenticationManager authenticationManager) {
        super(requiresAuthenticationRequestMatcher); // 将RequestMatcher传递给父类
        setAuthenticationManager(authenticationManager); // 设置认证管理器
    }

    /**
     * 实现JWT认证的核心逻辑。
     * 只有当RequestMatcher匹配时,此方法才会被调用。
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        // 在这里实现你的JWT解析和认证逻辑
        // 例如:从请求头中获取JWT令牌
        String authorizationHeader = request.getHeader("Authorization");
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            // 如果没有Bearer Token,抛出认证异常,或返回null让后续认证机制处理
            throw new AuthenticationException("Missing or invalid JWT token in Authorization header") {};
        }

        String jwtToken = authorizationHeader.substring(7); // 提取JWT字符串

        // TODO: 根据你的JWT库和业务逻辑验证jwtToken,并构建一个Authentication对象
        // 例如:
        // JwtAuthenticationToken authenticationToken = new JwtAuthenticationToken(jwtToken);
        // return getAuthenticationManager().authenticate(authenticationToken); // 委托给AuthenticationManager进行认证

        // 示例:此处仅为演示,实际应替换为你的JWT验证逻辑
        System.out.println("Processing JWT for path: " + request.getRequestURI());
        // 假设成功验证并返回一个Authentication对象
        // return new UsernamePasswordAuthenticationToken("user", null, Collections.emptyList());
        throw new UnsupportedOperationException("JWT认证逻辑待实现,请替换为实际的令牌验证和用户身份构建。");
    }

    // 可选:重写successfulAuthentication和unsuccessfulAuthentication方法来处理认证成功或失败后的逻辑
    // @Override
    // protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    //     super.successfulAuthentication(request, response, chain, authResult);
    //     // 认证成功后继续过滤器链
    //     chain.doFilter(request, response);
    // }

    // @Override
    // protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
    //     // 认证失败处理,例如返回401 Unauthorized
    //     response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    //     response.getWriter().write("Authentication Failed: " + failed.getMessage());
    // }
}

2. 定义 RequestMatcher

针对“只过滤/api/**路径”的需求,我们可以使用AntPathRequestMatcher。

import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

// 简单匹配单个路径模式
// RequestMatcher apiRequestMatcher = new AntPathRequestMatcher("/api/**");

// 如果需要匹配多个路径模式,可以使用OrRequestMatcher
// RequestMatcher multiPathMatcher = new OrRequestMatcher(
//     new AntPathRequestMatcher("/api/v1/**"),
//     new AntPathRequestMatcher("/secure/**")
// );

3. 配置 Spring Security

在你的安全配置类(通常是继承WebSecurityConfigurerAdapter或使用SecurityFilterChain)中,将改造后的CustomJwtAuthenticationFilter作为Bean注入,并添加到安全链中。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 假设你有一个JwtAuthenticationEntryPoint处理认证失败的入口点
    // @Autowired
    // private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    // 假设你有一个UserDetailsService用于加载用户详情(如果JWT认证需要)
    // @Autowired
    // private UserDetailsService userDetailsService;

    /**
     * 配置HTTP安全策略。
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable() // 禁用CSRF,因为JWT是无状态的
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 设置会话管理为无状态
            .and()
            // .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and() // 配置认证入口点处理未认证请求
            .authorizeRequests()
            .antMatchers("/api/**").authenticated() // 明确指定 /api/** 路径需要认证
            .anyRequest().permitAll() // 其他所有请求都允许访问
            .and()
            // 将我们定制的JWT过滤器添加到UsernamePasswordAuthenticationFilter之前
            .addFilterBefore(customJwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 将CustomJwtAuthenticationFilter注册为Spring Bean。
     * 注意:这里需要捕获AuthenticationManagerBean()抛出的异常。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

98

2025.08.06

spring boot框架优点
spring boot框架优点

spring boot框架的优点有简化配置、快速开发、内嵌服务器、微服务支持、自动化测试和生态系统支持。本专题为大家提供spring boot相关的文章、下载、课程内容,供大家免费下载体验。

135

2023.09.05

spring框架有哪些
spring框架有哪些

spring框架有Spring Core、Spring MVC、Spring Data、Spring Security、Spring AOP和Spring Boot。详细介绍:1、Spring Core,通过将对象的创建和依赖关系的管理交给容器来实现,从而降低了组件之间的耦合度;2、Spring MVC,提供基于模型-视图-控制器的架构,用于开发灵活和可扩展的Web应用程序等。

384

2023.10.12

Java Spring Boot开发
Java Spring Boot开发

本专题围绕 Java 主流开发框架 Spring Boot 展开,系统讲解依赖注入、配置管理、数据访问、RESTful API、微服务架构与安全认证等核心知识,并通过电商平台、博客系统与企业管理系统等项目实战,帮助学员掌握使用 Spring Boot 快速开发高效、稳定的企业级应用。

64

2025.08.19

Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性
Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性

Spring Boot 是一个基于 Spring 框架的 Java 开发框架,它通过 约定优于配置的原则,大幅简化了 Spring 应用的初始搭建、配置和开发过程,让开发者可以快速构建独立的、生产级别的 Spring 应用,无需繁琐的样板配置,通常集成嵌入式服务器(如 Tomcat),提供“开箱即用”的体验,是构建微服务和 Web 应用的流行工具。

11

2025.12.22

Java Spring Boot 微服务实战
Java Spring Boot 微服务实战

本专题深入讲解 Java Spring Boot 在微服务架构中的应用,内容涵盖服务注册与发现、REST API开发、配置中心、负载均衡、熔断与限流、日志与监控。通过实际项目案例(如电商订单系统),帮助开发者掌握 从单体应用迁移到高可用微服务系统的完整流程与实战能力。

101

2025.12.24

json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

403

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

528

2023.08.23

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号