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

Spring应用中同时配置JWT与Basic认证及路径分流认证方案

当然可以实现!在Spring Security中,通过配置多个独立的安全规则(不管是用传统的WebSecurityConfigurerAdapter还是新版本的SecurityFilterChain)就能完美满足你的需求——让特定路径走Basic认证,其他路径保持JWT认证。我给你详细讲下具体操作:

实现方案:多安全规则配置

核心思路是给不同的路径范围配置独立的安全规则,并通过优先级控制让Spring先匹配到/restexternal/**路径的Basic认证规则,再处理其他路径的JWT规则。

方式一:基于WebSecurityConfigurerAdapter(兼容旧版本)

如果你的项目还在使用Spring Security 5.7之前的版本,可以用这种传统方式:

1. 配置Basic认证的安全类(高优先级)

这个类专门接管/restexternal/**路径的认证,启用Basic认证:

import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
@Order(1) // 数字越小优先级越高,确保先匹配这个规则
public class BasicAuthSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/restexternal/**") // 只对该路径下的请求生效
            .authorizeRequests()
                .anyRequest().authenticated() // 要求所有该路径的请求必须认证
                .and()
            .httpBasic() // 启用Basic认证
            .and()
            .csrf().disable(); // 根据业务场景决定是否关闭CSRF,外部接口通常关闭
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 示例:内存中配置用户,实际项目可以替换为从数据库/配置中心读取
        auth.inMemoryAuthentication()
            .passwordEncoder(new BCryptPasswordEncoder())
            .withUser("external_api_user")
            .password(new BCryptPasswordEncoder().encode("SecurePass123!"))
            .roles("EXTERNAL");
    }
}

2. 配置JWT认证的安全类(低优先级)

这个类处理除/restexternal/**外的所有请求,继续使用你的JWT过滤器:

import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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;

@Configuration
@EnableWebSecurity
@Order(2)
public class JwtAuthSecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    public JwtAuthSecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/**") // 匹配所有路径,但会被高优先级规则先拦截
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) // 添加JWT过滤器
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // JWT无状态,禁用session
    }
}

方式二:基于SecurityFilterChain(Spring 5.7+推荐)

从Spring Security 5.7开始,官方不再推荐WebSecurityConfigurerAdapter,改用基于组件的配置方式,更灵活:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    // Basic认证规则:高优先级
    @Bean
    @Order(1)
    public SecurityFilterChain basicAuthFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatcher("/restexternal/**")
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .httpBasic()
            .and()
            .csrf().disable();
        return http.build();
    }

    // JWT认证规则:低优先级
    @Bean
    @Order(2)
    public SecurityFilterChain jwtAuthFilterChain(HttpSecurity http, JwtAuthenticationFilter jwtAuthenticationFilter) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
            .csrf().disable()
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            );
        return http.build();
    }

    // 密码编码器,全局共用
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
关键注意事项
  • 优先级控制:通过@Order注解设置规则的匹配顺序,数字越小越先被匹配。/restexternal/**的规则必须放在前面,这样Spring会优先用Basic认证处理这些请求,不会走到JWT的规则里。
  • 启用Basic认证的核心:只需要在对应的安全规则里调用.httpBasic()方法,Spring会自动处理Authorization: Basic xxxx请求头的解析和认证逻辑,不需要额外写过滤器。
  • 路径隔离:每个安全规则通过antMatcher(旧版)或securityMatcher(新版)限定生效范围,避免规则冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:12:19