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

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();
}

关键配置说明

  1. @Order注解:Spring Security按Order值从小到大执行FilterChain,API的FilterChain优先级更高(@Order(1)),确保/api/**请求先被匹配处理。
  2. securityMatcher:明确每个FilterChain的处理范围,避免两个认证逻辑冲突。API的FilterChain仅处理/api/**,普通页面的处理剩余所有请求。
  3. 授权规则调整:普通页面需开放登录/登出路径的匿名访问权限,其余页面强制认证;API路径则要求所有请求必须通过API Key认证。
  4. 会话策略:API采用无状态会话(STATELESS),符合RESTful接口规范;普通页面保留默认有状态会话。
  5. 异常处理适配:API认证失败直接返回HTTP 401状态码,普通页面则跳转至登录页,适配不同场景的用户体验。

注意:确保你的AuthenticationFilter实现正确,能从请求头、参数或指定位置提取API Key,并完成认证逻辑(比如与数据库存储的Key比对)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:43:21