Spring Boot Security:为API与控制器配置不同SecurityFilterChain
实现Spring Boot双认证机制:API路径用API Key,普通页面用账号密码
要让/api/**路径走API Key认证,其余路径走账号密码登录认证,核心是利用Spring Security的多SecurityFilterChain特性,通过@Order指定优先级,并用securityMatcher划分各自负责的请求范围。以下是具体配置方案:
步骤1:配置普通页面的SecurityFilterChain(账号密码登录)
这个FilterChain负责除/api/**之外的所有请求,用表单登录保护页面:
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import static org.springframework.security.config.Customizer.withDefaults; @Bean @Order(2) // 优先级低于API的FilterChain public SecurityFilterChain webSecurityFilterChain(HttpSecurity http) throws Exception { return http // 限定仅处理非/api路径的请求 .securityMatcher(AntPathRequestMatcher.antMatcher("/**").negate(AntPathRequestMatcher.antMatcher("/api/**"))) .cors(withDefaults()) .csrf(csrf -> csrf.disable()) // 普通页面若需CSRF可保留,按需调整 .authorizeHttpRequests(authorize -> authorize // 登录页、登出相关路径允许匿名访问 .requestMatchers("/login", "/login?*").permitAll() // 其余普通页面必须认证后访问 .anyRequest().authenticated()) .formLogin(form -> form .loginPage("/login") .failureUrl("/login?loginError=true") .permitAll()) .logout(logout -> logout .logoutSuccessUrl("/login?logoutSuccess=true") .deleteCookies("JSESSIONID") .permitAll()) .exceptionHandling(exception -> exception .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login?loginRequired=true"))) .build(); }
步骤2:配置API路径的SecurityFilterChain(API Key认证)
这个FilterChain仅负责/api/**路径,采用无状态的API Key认证:
import org.springframework.http.HttpStatus; import org.springframework.security.web.authentication.HttpStatusEntryPoint; import static org.springframework.security.config.Customizer.withDefaults; @Bean @Order(1) // 优先级更高,先匹配/api路径的请求 public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception { return http // 限定仅处理/api/**路径的请求 .securityMatcher("/api/**") .csrf(AbstractHttpConfigurer::disable) // 无状态API禁用CSRF .authorizeHttpRequests(auth -> auth .anyRequest().authenticated()) // 所有API请求必须认证 .httpBasic(withDefaults()) // 若你的API Key认证基于HTTP Basic则保留,否则替换为对应认证方式 .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // API采用无状态会话 .addFilterBefore(new AuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) // 自定义API Key认证过滤器 .exceptionHandling(ex -> ex // API认证失败直接返回401,不跳转登录页 .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))) .build(); }
关键配置说明
- @Order注解:Spring Security按Order值从小到大执行FilterChain,API的FilterChain优先级更高(
@Order(1)),确保/api/**请求先被匹配处理。 - securityMatcher:明确每个FilterChain的处理范围,避免两个认证逻辑冲突。API的FilterChain仅处理
/api/**,普通页面的处理剩余所有请求。 - 授权规则调整:普通页面需开放登录/登出路径的匿名访问权限,其余页面强制认证;API路径则要求所有请求必须通过API Key认证。
- 会话策略:API采用无状态会话(
STATELESS),符合RESTful接口规范;普通页面保留默认有状态会话。 - 异常处理适配:API认证失败直接返回HTTP 401状态码,普通页面则跳转至登录页,适配不同场景的用户体验。
注意:确保你的
AuthenticationFilter实现正确,能从请求头、参数或指定位置提取API Key,并完成认证逻辑(比如与数据库存储的Key比对)。
内容的提问来源于stack exchange,提问作者coverDJ234
相关产品推荐
相关产品推荐

