Spring Boot中跨域和请求参数处理问题
在开发过程中,我遇到了以下问题:在使用 Spring Boot 作为后端时,前端通过 AJAX 向后端发送请求,却报错如下:
问题描述
-
CORS跨域错误:
Access to XMLHttpRequest at 'http://localhost:8080/users/login' from origin 'http://127.0.0.1:5000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
- 前端运行在
http://127.0.0.1:5000
,后端运行在http://localhost:8080
。 - 因前后端跨域,浏览器拦截请求。
- 前端运行在
-
请求参数错误:
org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'username' for method parameter type String is not present
- 后端接口使用
@RequestParam
注解接收参数,但报错提示缺少username
参数。 - 可能的原因是前端未正确发送请求,或者参数格式与后端要求不符。
- 后端接口使用
问题分析
以上两个问题主要涉及以下几个方面:
-
跨域问题(CORS):
- 前后端运行在不同域(不同的协议、域名或端口号),触发了浏览器的跨域请求限制。
- 后端未正确配置
Access-Control-Allow-Origin
响应头。
-
请求参数缺失:
- 后端代码使用
@RequestParam
接收参数,默认要求参数必须传递。 - 如果前端未正确传递参数(如参数名称或格式不对),后端会抛出
MissingServletRequestParameterException
。
- 后端代码使用
解决方案
1. 解决跨域问题
在 Spring Boot 的 SecurityConfig
中正确配置 CORS:
- 启用全局 CORS 配置,允许前端域名访问后端接口。
- 确保后端接口响应中返回
Access-Control-Allow-Origin
和相关的 CORS 头信息。
以下是完整的 SecurityConfig
配置:
@Configuration
public class SecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.csrf(csrf -> csrf.disable()) // 禁用 CSRF 防护.cors(Customizer.withDefaults()) // 启用 CORS.authorizeHttpRequests(auth -> auth.anyRequest().permitAll() // 允许所有请求匿名访问);return http.build();}@BeanCorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.setAllowedOrigins(Arrays.asList("http://127.0.0.1:5000", "http://localhost:5000")); // 允许的来源configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); // 允许的HTTP方法configuration.setAllowCredentials(true); // 是否允许发送Cookieconfiguration.setAllowedHeaders(Arrays.asList("*")); // 允许的请求头UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration);return source;}
}
验证:
- 重启后端服务,确保前端请求时返回的响应头中包含:
Access-Control-Allow-Origin: http://127.0.0.1:5000
2. 解决请求参数缺失问题
2.1 检查后端代码
后端代码如下,使用 @RequestParam
接收参数:
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {return userService.login(username, password);
}
问题原因:
- 前端未以
username
和password
的形式传递参数。
2.2 检查前端请求
确保前端发送的参数与后端匹配。如果使用表单提交,确保参数名正确:
$.ajax({url: 'http://localhost:8080/users/login',type: 'POST',data: {username: 'testUser', // 参数名必须与后端一致password: 'testPassword'},success: function (response) {console.log('登录成功:', response);},error: function (error) {console.log('登录失败:', error);}
});
如果前端发送 JSON 格式请求,则需要修改后端代码,使用 @RequestBody
接收请求体:
前端代码:
$.ajax({url: 'http://localhost:8080/users/login',type: 'POST',contentType: 'application/json', // 设置请求格式为 JSONdata: JSON.stringify({username: 'testUser',password: 'testPassword'}),success: function (response) {console.log('登录成功:', response);},error: function (error) {console.log('登录失败:', error);}
});
后端代码:
@PostMapping("/login")
public String login(@RequestBody Map<String, String> loginRequest) {String username = loginRequest.get("username");String password = loginRequest.get("password");return userService.login(username, password);
}
3. 前后端参数名称不一致
确保前端与后端使用的参数名称一致。如果前端参数名为 userName
和 passWord
,后端需要同步修改:
@PostMapping("/login")
public String login(@RequestParam("userName") String username, @RequestParam("passWord") String password) {return userService.login(username, password);
}
总结
通过以上方法,解决了 Spring Boot 项目中跨域问题和请求参数缺失的问题:
-
跨域问题:
- 在 Spring Security 中启用
.cors()
配置。 - 使用
CorsConfigurationSource
配置允许的来源、方法和头信息。
- 在 Spring Security 中启用
-
请求参数问题:
- 确保前端发送的参数格式正确,参数名称与后端一致。
- 根据前端请求格式(表单或 JSON),调整后端使用
@RequestParam
或@RequestBody
。
最终效果:
- 前后端成功交互,解决跨域问题。
- 后端能够正确接收到
username
和password
参数,完成用户登录操作。