You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3中如何为不同接口分别配置mTLS与JWT认证?

Spring Boot 3.0.5 多认证方式(JWT/mTLS)优化实现方案

场景说明

我的应用基于Spring Boot 3.0.5(JDK 17),包含三类API接口:

  • /api/**:供客户端UI调用,采用JWT认证
  • /integration/**:供其他服务应用调用,需通过mTLS客户端证书保护
  • 其余接口:公开访问,无需认证

当前已将server.ssl.client-auth设置为want,避免所有接口强制启用X509认证;通过两个SecurityFilterChain加自定义过滤器实现了需求,但自定义校验逻辑过多,希望找到更简洁、原生的优化方案。

当前核心配置代码如下:

// JWT认证配置
@Bean
public SecurityFilterChain configureSecurityFilters(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(a -> a
            .requestMatchers(new AntPathRequestMatcher("/api/**")).authenticated()
            .anyRequest().permitAll()
        )
        .csrf().disable()
        .addFilterBefore(jwtValidationFilter, UsernamePasswordAuthenticationFilter.class);
    return http.build();
}

// mTLS认证配置
@Bean
@Order(1)
public SecurityFilterChain x502Config(HttpSecurity http, HttpServletRequest request) throws Exception {
    http
        .securityMatcher("/integration/**")
        .csrf().disable()
        .addFilterBefore(customX509AuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
        .authorizeHttpRequests()
            .anyRequest().permitAll();
    return http.build();
}

优化方案

1. 替换自定义mTLS过滤器,使用Spring Security原生X509支持

Spring Security内置了X509AuthenticationFilter,可直接处理客户端证书的提取与认证,无需自定义过滤器。只需结合UserDetailsService完成证书用户的合法性校验即可:

@Bean
@Order(1)
public SecurityFilterChain mtlsSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher("/integration/**")
        .csrf(csrf -> csrf.disable())
        // 启用原生X509认证
        .x509(x509 -> x509
            // 从证书主题中提取CN作为用户名,正则可根据实际证书格式调整
            .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
            // 自定义UserDetailsService,校验该CN是否为合法的服务调用方
            .userDetailsService(certificateUserDetailsService)
        )
        .authorizeHttpRequests(auth -> auth
            // mTLS认证通过后才允许访问
            .anyRequest().authenticated()
        );
    return http.build();
}

其中certificateUserDetailsService是自定义的UserDetailsService实现,只需根据提取的CN(用户名)查询是否为允许的服务调用方,返回对应的UserDetails对象即可。

2. 用Spring Security OAuth2 Resource Server简化JWT认证

引入spring-boot-starter-oauth2-resource-server依赖后,可直接使用原生JWT支持,替代自定义的jwtValidationFilter:

首先添加Maven依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

然后配置JWT认证的SecurityFilterChain:

@Bean
@Order(2)
public SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher("/api/**")
        .csrf(csrf -> csrf.disable())
        .oauth2ResourceServer(oauth2 -> oauth2
            .jwt(jwt -> jwt
                // 可选:自定义JWT转换为Authentication的逻辑,比如提取自定义Claims
                .jwtAuthenticationConverter(customJwtAuthenticationConverter())
            )
        )
        .authorizeHttpRequests(auth -> auth
            .anyRequest().authenticated()
        );
    return http.build();
}

在配置文件中添加JWT验证的必要配置(根据你的认证服务器类型选择):

# 若使用JWKS端点验证
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://your-auth-server/.well-known/jwks.json

# 若使用本地公钥验证
# spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:public-key.pem

3. 拆分公开接口的独立配置

将公开接口的逻辑单独拆分为一个SecurityFilterChain,按顺序最后匹配,结构更清晰:

@Bean
@Order(3)
public SecurityFilterChain publicSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .anyRequest().permitAll()
        )
        .csrf(csrf -> csrf.disable()); // 公开接口通常无需CSRF保护,可根据实际需求调整
    return http.build();
}

优化优势

  • 大幅减少自定义代码,依赖Spring Security原生组件,降低维护成本与出错概率
  • 认证逻辑标准化,原生组件已覆盖证书解析、JWT签名校验、过期检查等核心逻辑
  • 配置结构清晰,三个SecurityFilterChain按Order优先级依次匹配接口,职责明确

内容的提问来源于stack exchange,提问作者JimJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 23:30:29