Maven运行Spring Boot项目时POST请求出现401未授权错误求助
问题描述
- 技术栈:Java 21 + Spring Boot 3.2.4,IntelliJ IDEA开发
- 本地IDE启动(运行按钮/Control+R):端口3000的React前端可正常向
http://localhost:8080/api/v1/register发送POST请求,用户数据成功存入本地3306端口的MySQL数据库 - Maven命令启动(执行
mvn clean package后用mvn spring-boot:run):相同的POST请求返回401(Unauthorized)错误 - 需求:解决该权限拦截问题,同时方案需适配Docker部署的MySQL
相关代码
WebConfig.java
package com.cinema.backend.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import java.util.Arrays; @Configuration public class WebConfig { private static final long MAX_AGE = 3600L; @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:3000"); config.setAllowedHeaders(Arrays.asList( "Authorization", "Cache-Control", "Content-Type")); config.setAllowedMethods(Arrays.asList( HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.OPTIONS.name())); config.setMaxAge(MAX_AGE); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }
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.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.cinema</groupId> <artifactId>backend</artifactId> <version>0.0.1-SNAPSHOT</version> <name>backend</name> <description>Backend Application for Cinema</description> <properties> <java.version>21</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <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>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
UserController.java
package com.cinema.backend.controller; import com.cinema.backend.models.User; import com.cinema.backend.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private UserRepository userRepository; @PostMapping("/api/v1/register") User newUser(@RequestBody User newUser){ return userRepository.save(newUser); } }
解决方案
1. 添加Spring Security配置类
创建SecurityConfig.java,明确放行注册接口的匿名访问权限,同时适配CORS规则:
package com.cinema.backend.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.CorsConfiguration; import java.util.Arrays; @Configuration @EnableWebSecurity public class SecurityConfig { private final WebConfig webConfig; public SecurityConfig(WebConfig webConfig) { this.webConfig = webConfig; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 关闭CSRF防护:跨域POST请求默认会被CSRF拦截,注册接口无需CSRF验证 .csrf(csrf -> csrf.disable()) // 配置CORS规则 .cors(cors -> cors.configurationSource(corsConfigurationSource())) // 接口权限控制 .authorizeHttpRequests(auth -> auth // 允许匿名访问注册接口 .requestMatchers("/api/v1/register").permitAll() // 其他所有接口需要认证 .anyRequest().authenticated() ); // 将自定义CorsFilter置于Security认证过滤器之前,确保CORS规则优先生效 http.addFilterBefore(webConfig.corsFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:3000"); config.setAllowedHeaders(Arrays.asList( "Authorization", "Cache-Control", "Content-Type")); config.setAllowedMethods(Arrays.asList( "GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
2. 适配Docker部署的MySQL
修改src/main/resources/application.properties,根据Docker环境调整数据库连接配置:
# 数据库连接配置 # 本地MySQL使用localhost;Docker容器中若用自定义网络,替换为MySQL容器名(如mysql-container) spring.datasource.url=jdbc:mysql://localhost:3306/你的数据库名?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true spring.datasource.username=你的数据库用户名 spring.datasource.password=你的数据库密码 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
3. 验证Maven启动配置
- 确认
application.properties位于src/main/resources目录,Maven打包时会自动将其加入target/classes - 执行
mvn clean package后,检查target/classes下是否存在该配置文件 - 启动时可添加日志参数排查配置加载:
mvn spring-boot:run -Dlogging.level.org.springframework=DEBUG
问题根源
IDE启动时默认加载开发环境配置(如application-dev.properties),可能已临时放开权限或关闭Security;而Maven命令启动默认加载application.properties,Spring Security默认对所有接口启用认证,导致注册接口被拦截返回401。
内容的提问来源于stack exchange,提问作者Egon
相关产品推荐
相关产品推荐

