Spring Boot 3.2.2嵌入Tomcat报403,外部Tomcat正常问题咨询
问题描述
我有一个Spring Boot 3.2.2应用,打包为WAR文件部署到外部Tomcat v10.1.18时,Postman及Angular应用均可正常访问控制器;但在IntelliJ或Eclipse中使用嵌入Tomcat v10.1.18运行时,Postman和Angular请求均返回403错误。这种反常现象是否由安全升级导致?
服务器调试日志
21:46:47.590 [http-nio-8080-exec-2] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet' 21:46:47.590 [http-nio-8080-exec-2] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet' 21:46:47.590 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Detected StandardServletMultipartResolver 21:46:47.590 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Detected AcceptHeaderLocaleResolver 21:46:47.590 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Detected FixedThemeResolver 21:46:47.591 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@6fe243a 21:46:47.591 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Detected org.springframework.web.servlet.support.SessionFlashMapManager@575c23f1 21:46:47.591 [http-nio-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data 21:46:47.591 [http-nio-8080-exec-2] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 1 ms 21:46:47.602 [http-nio-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - Securing POST /api/v1/sayHello 21:46:47.615 [http-nio-8080-exec-2] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext 21:46:47.615 [http-nio-8080-exec-2] DEBUG o.s.s.w.s.SessionManagementFilter - Request requested invalid session id F116C9F04B2809C02E15348F58666EFA 21:46:47.616 [http-nio-8080-exec-2] DEBUG o.s.s.w.a.Http403ForbiddenEntryPoint - Pre-authenticated entry point called. Rejecting access 21:46:47.623 [http-nio-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - Securing POST /error 21:46:47.623 [http-nio-8080-exec-2] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext 21:46:47.623 [http-nio-8080-exec-2] DEBUG o.s.s.w.a.Http403ForbiddenEntryPoint - Pre-authenticated entry point called. Rejecting access
相关代码配置
SecurityConfiguration.java
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(AbstractHttpConfigurer::disable) .cors(httpSecurityCorsConfigurer -> httpSecurityCorsConfigurer.configurationSource(corsConfigurationSource())) .authorizeHttpRequests(request -> request.requestMatchers("/api/v1/**") .permitAll().anyRequest().authenticated()) .sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS)) .authenticationProvider(authenticationProvider()).addFilterBefore( jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedOrigins(List.of("http://localhost:4200")); corsConfiguration.setAllowedMethods(List.of("GET", "POST")); corsConfiguration.setAllowCredentials(true); corsConfiguration.setAllowedHeaders(List.of("*")); corsConfiguration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfiguration); return source; }
Application.java
@SpringBootApplication public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.2</version> <relativePath/> </parent> <groupId>com.xpo.api</groupId> <artifactId>mapgs</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>mapgs api</name> <description>mapgs API</description> <properties> <start-class>com.xpo.api.Application</start-class> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
分析与解决方案
从日志可以定位核心问题:
- 请求携带了无效的
JSESSIONID,而你的配置中设置了sessionCreationPolicy(STATELESS)(无状态模式) - Spring Security的
SessionManagementFilter检测到无效session ID后,触发默认的Http403ForbiddenEntryPoint,直接返回403
外部Tomcat正常、内嵌Tomcat报错的差异,是两者对session Cookie的处理逻辑不同:外部Tomcat自动忽略了无效的JSESSIONID,而内嵌Tomcat下Spring Security的过滤器链严格执行了无状态模式的校验规则。
解决步骤
调整无效session校验逻辑
在sessionManagement配置中添加无效session处理策略,让无状态模式下跳过无效session校验:import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; .sessionManagement(manager -> manager .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .invalidSessionStrategy(new NullAuthenticatedSessionStrategy()) )验证JWT过滤器有效性
日志显示请求进入了匿名上下文,说明jwtAuthenticationFilter可能未正确解析token或未生效:- 确认过滤器是否拦截了所有
/api/v1/**路径的请求 - 检查过滤器是否将解析后的用户信息正确设置到
SecurityContextHolder中
- 确认过滤器是否拦截了所有
修正WAR打包配置
pom.xml中packaging设置为jar不符合WAR打包需求,需修改:<packaging>war</packaging>同时将内嵌Tomcat依赖设为
provided,避免与外部Tomcat冲突:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>清除无效Cookie
测试时先清除Postman或浏览器中的JSESSIONIDCookie;如果是Angular应用,无状态模式下可将withCredentials设为false(无需携带Cookie时)。
内容的提问来源于stack exchange,提问作者softechie
相关产品推荐
相关产品推荐

