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
相关产品推荐
相关产品推荐

