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

Spring Boot多认证配置异常:API Key端点报SecurityContext无认证对象

问题原因及修复方案

出现"An Authentication object was not found in the SecurityContext"错误的核心原因:

  • 第一个SecurityFilterChain(API Key专用)缺少授权规则配置,Spring Security无法识别你通过过滤器设置的认证对象
  • 使用普通Filter而非Spring Security推荐的OncePerRequestFilter,可能导致过滤器执行逻辑不符合Security链的预期

具体修复步骤

1. 完善API Key专用的SecurityFilterChain配置

在filterChainPrivate方法中添加授权规则和无状态会话配置:

@Bean
@Order(1)
public SecurityFilterChain filterChainPrivate(HttpSecurity http) throws Exception {
    http
        .securityMatcher("/specificEndpointToAuthoriseWithApiKey")
        // 明确所有匹配的请求需要认证
        .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
        // 配置无状态会话(API Key认证不需要会话)
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .addFilterBefore(new InternalApiKeyAuthenticationFilter(), ChannelProcessingFilter.class);
    http.cors(AbstractHttpConfigurer::disable);
    http.csrf(AbstractHttpConfigurer::disable);
    http.exceptionHandling(httpSecurityExceptionHandlingConfigurer -> {
        httpSecurityExceptionHandlingConfigurer.accessDeniedHandler(getAccessDeniedHandler());
        httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(getAuthenticationEntryPoint());
    });
    return http.build();
}

2. 将API Key过滤器改为继承OncePerRequestFilter

替换普通Filter实现为Spring Security专用的OncePerRequestFilter,确保每个请求仅执行一次认证逻辑:

import org.springframework.web.filter.OncePerRequestFilter;

public class InternalApiKeyAuthenticationFilter extends OncePerRequestFilter {
    private final String internalApiKey = "123456";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String apiKey = request.getHeader("x-api-key");

        if (apiKey == null) {
            unauthorized(response);
            return;
        }

        if (!internalApiKey.equals(apiKey)) {
            unauthorized(response);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                "apiKeyUser", null, Collections.singletonList(new SimpleGrantedAuthority("ebf-adapter")));
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(request, response);
    }

    private void unauthorized(HttpServletResponse httpServletResponse) throws IOException {
        httpServletResponse.setHeader(com.google.common.net.HttpHeaders.CONTENT_TYPE, org.springframework.http.MediaType.APPLICATION_JSON_VALUE);
        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        Map<String, Object> response = Map.of("message", "SC_UNAUTHORIZED");
        String responseBody = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(response);
        httpServletResponse.getWriter().write(responseBody);
    }
}

3. (可选)将过滤器交由Spring容器管理

在SecurityConfiguration中添加过滤器的Bean定义,避免手动实例化:

@Bean
public InternalApiKeyAuthenticationFilter internalApiKeyAuthenticationFilter() {
    return new InternalApiKeyAuthenticationFilter();
}

然后修改filterChainPrivate中的过滤器引用:

.addFilterBefore(internalApiKeyAuthenticationFilter(), ChannelProcessingFilter.class);

4. 修正第二个SecurityFilterChain的语法错误

你的第二个FilterChain代码存在括号未闭合的问题,同时补充JWT资源服务器配置:

@Bean
@Order(2)
SecurityFilterChain filterChain(HttpSecurity http,
        Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter) throws Exception {

    http.authorizeHttpRequests(accessManagement -> accessManagement
            .requestMatchers(new AntPathRequestMatcher("/api-docs/**"))
            .permitAll()
            .anyRequest().authenticated()
    );
    // 配置JWT资源服务器
    http.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter)));
    return http.build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:45:12