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

Spring Security配置问题:如何让REST接口同时支持API Key认证和用户登录会话认证

Spring Security配置问题:如何让REST接口同时支持API Key认证和用户登录会话认证

你遇到的核心问题在于REST接口的SecurityFilterChain设置了STATELESS会话策略,这会让Spring Security完全忽略请求中的会话(JSESSIONID),同时该FilterChain里只配置了APIKeyFilter,没有处理会话认证的逻辑。下面给你一步步拆解解决方案:

问题根源分析

你的filterChainREST中设置了sessionCreationPolicy(SessionCreationPolicy.STATELESS),这个配置会告诉Spring Security:

  1. 不会为REST请求创建新会话
  2. 完全不读取或使用已有的会话信息
    所以即使请求带着已登录用户的JSESSIONID,这个FilterChain也不会去解析会话里的认证数据,直接进入APIKeyFilter的逻辑——如果没有API Key就会走到后续的权限校验,自然会被拒绝。

解决方案步骤

1. 调整REST FilterChain的会话策略

把REST接口的会话策略从STATELESS改为SessionCreationPolicy.IF_REQUIRED(或者直接删掉这行,因为默认就是这个值),让Spring Security允许使用已有的会话:

2. 确保REST FilterChain支持会话认证

去掉STATELESS后,Spring Security会自动添加会话相关的过滤器(比如SessionAuthenticationFilter),这些过滤器会解析请求中的JSESSIONID,加载会话里的用户认证信息。

3. 保留APIKeyFilter的逻辑(无需修改核心逻辑)

你的APIKeyFilter逻辑是对的:当找到有效API Key时设置认证信息,没有找到时直接放行让后续过滤器处理——现在后续过滤器就会处理会话认证了。

修改后的完整代码示例

@Bean
@Order(1)
public SecurityFilterChain filterChainREST(HttpSecurity http) 
       throws Exception
{
    APIKeyFilter filter = new APIKeyFilter(API_KEYS);
    http.antMatcher("/api/**")
            .addFilterBefore(filter, AnonymousAuthenticationFilter.class)
            .csrf().disable()
            .authorizeHttpRequests(requests -> requests
                    .antMatchers("/api/1/mgr/**").hasAnyRole("ADMIN", "MGR")
                    .antMatchers("/api/1/admin/**").hasRole("ADMIN")
                    .anyRequest().denyAll())
            .sessionManagement()
                // 替换为IF_REQUIRED,允许使用已有会话
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);

    return http.build();
}

@Bean
@Order(2)
public SecurityFilterChain filterChainWebUI(HttpSecurity http) 
       throws Exception
{
    http
            .antMatcher("/**") // 处理/api/**之外的所有请求
            .csrf().disable()
            .authorizeHttpRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/mgr/**").hasAnyRole("ADMIN", "MGR")
            .antMatchers("/login*").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin(Customizer.withDefaults())
            .logout(l->l.deleteCookies("JSESSIONID"))
            .sessionManagement()
                 .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .and()
            .exceptionHandling().accessDeniedPage("/error/accessDenied.html");
    return http.build();
}

验证效果

修改完成后,访问/api/**接口时会有两种认证路径:

  1. 带有效API Key:APIKeyFilter会直接设置认证信息,完成权限校验后放行
  2. 不带API Key但有有效JSESSIONID:Spring Security会自动从会话中加载已登录用户的认证信息,再进行权限校验,符合角色要求就会放行
  3. 两者都没有:会被权限校验规则拒绝

备注:内容来源于stack exchange,提问作者mwhidden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:23:14