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

Spring Boot启动报错No ServletContext set:方法安全注解与异常解析器冲突

解决方案:Spring Security 6.1.0 同时使用@EnableMethodSecurity与自定义AuthenticationEntryPoint的"No ServletContext set"异常

问题根源

@EnableMethodSecurity会触发方法安全相关Bean的提前初始化,而自定义的delegatedAuthenticationEntryPoint依赖的ServletContext此时尚未完成注入,导致启动时抛出异常。

具体解决方法

方法1:注入AuthenticationEntryPoint时添加@Lazy注解

在SecurityConfig的注入点上添加@Lazy,延迟AuthenticationEntryPoint的初始化,直到ServletContext就绪:

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    private final AuthenticationEntryPoint authenticationEntryPoint;

    public SecurityConfig(
            @Lazy @Qualifier("delegatedAuthenticationEntryPoint") 
            AuthenticationEntryPoint authenticationEntryPoint
    ) {
        this.authenticationEntryPoint = authenticationEntryPoint;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .exceptionHandling(exceptions -> exceptions
                        .authenticationEntryPoint(authenticationEntryPoint)
                )
                .authorizeHttpRequests(auth -> auth
                        .anyRequest().authenticated()
                );
        return http.build();
    }
}

方法2:让自定义AuthenticationEntryPoint实现ServletContextAware接口

确保ServletContext被正确注入到自定义EntryPoint中,避免初始化时依赖缺失:

@Component("delegatedAuthenticationEntryPoint")
public class DelegatedAuthenticationEntryPoint 
        implements AuthenticationEntryPoint, ServletContextAware {

    private final ObjectMapper objectMapper;
    private ServletContext servletContext;

    public DelegatedAuthenticationEntryPoint(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Override
    public void commence(HttpServletRequest request, 
                         HttpServletResponse response, 
                         AuthenticationException authException) 
            throws IOException, ServletException {
        // 自定义未授权响应逻辑
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        objectMapper.writeValue(response.getWriter(), 
                Map.of("code", 401, "message", "未授权访问资源"));
    }
}

方法3:给自定义EntryPoint的Bean添加@Lazy注解

如果自定义EntryPoint依赖了其他Web相关Bean,直接给EntryPoint的Bean标注@Lazy,延迟其初始化时机:

@Lazy
@Component("delegatedAuthenticationEntryPoint")
public class DelegatedAuthenticationEntryPoint implements AuthenticationEntryPoint {
    // 自定义异常处理逻辑
}

验证

启动应用后,既可以正常使用@PreAuthorize进行方法权限校验,同时自定义的AuthenticationEntryPoint也能正确处理未授权异常,不再抛出"No ServletContext set"错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:14:54