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
相关产品推荐
相关产品推荐

