前端调用Spring Boot后端验证OTP时遇CORS拦截问题求助
解决Spring Boot + 前端的CORS跨域及OTP验证请求问题
问题背景
我是编程新手,和同伴合作开发项目,前端采用HTML/CSS/JS,后端基于Java Spring Boot。在实现OTP验证功能时遇到CORS策略拦截错误,控制台提示响应缺少Access-Control-Allow-Origin头。
后端代码
@RestController @RequestMapping("/api/users") @CrossOrigin(origins = "*",maxAge = 3600) public class UserController { @Autowired private UserService userService; @PatchMapping("/verify") @Operation(summary = "Customer enters OTP code", description = "Check if OTP information is correct, if correct, enable it so the customer can log in") public ResponseEntity<?> authtotp(@RequestParam(name = "otp") String otp) { userService.verifyAccount(otp); return ResponseEntity.ok().build(); } public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); UrlBasedCorsConfigurationSource cors = new UrlBasedCorsConfigurationSource(); cors.registerCorsConfiguration("/**", config); return cors; } }
前端代码
function verifyOtp() { const otp1 = document.getElementById("opt1").value; const otp2 = document.getElementById("opt2").value; const otp3 = document.getElementById("opt3").value; const otp4 = document.getElementById("opt4").value; const otp5 = document.getElementById("opt5").value; const otp = otp1 + otp2 + otp3 + otp4 + otp5; axios.patch("http://localhost:8080/api/users/verify", { otp: otp }) .then(response => { document.getElementById("verification-message").innerText = "Account verified successfully"; document.getElementById("verification-message").style.color = "green"; setTimeout(() => { window.location.href = "login.html"; }, 3000); }) .catch(error => { console.error("Error verifying OTP:", error.response.data.error); document.getElementById("verification-message").innerText = "Wrong OTP CODE!!"; document.getElementById("verification-message").style.color = "red"; }); } document.addEventListener("DOMContentLoaded", function() { document.querySelector("button").addEventListener("click", function(event) { event.preventDefault(); verifyOtp(); }); });
控制台报错信息
Access to XMLHttpRequest at 'http://localhost:8080/api/users/verify' from origin 'http://127.0.0.1:5500' 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. xhr.js:258 PATCH http://localhost:8080/api/users/verify net::ERR_FAILED (anonymous) @ xhr.js:258 xhr @ xhr.js:49 qe @ dispatchRequest.js:51 value @ Axios.js:170 (anonymous) @ Axios.js:40 f @ axios.min.js:1 (anonymous) @ axios.min.js:1 (anonymous) @ axios.min.js:1 o @ axios.min.js:1 s @ Axios.js:38 (anonymous) @ Axios.js:38 n @ Axios.js:38 s.value @ Axios.js:60 (anonymous) @ Axios.js:209 (anonymous) @ bind.js:5 verifyOtp @ verifyaccount.js:37 (anonymous) @ verifyaccount.js:55 verifyaccount.js:46 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'data') at verifyaccount.js:46:66
问题分析与解决方法
1. CORS配置冲突问题
当前代码同时使用了@CrossOrigin注解和自定义的corsConfigurationSource方法,但自定义方法未被Spring容器识别,且两种配置可能产生冲突,导致预请求(OPTIONS)未被正确处理。
解决方式:
全局CORS配置(推荐):
创建独立的配置类,注册全局CORS规则,移除控制器上的@CrossOrigin注解避免冲突:@Configuration public class WebConfig { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); // 生产环境建议替换为具体前端域名,例如"http://127.0.0.1:5500" config.setAllowedOriginPatterns(Collections.singletonList("*")); // 明确允许PATCH和OPTIONS方法(预请求需要OPTIONS) config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); config.setAllowedHeaders(Collections.singletonList("*")); config.setAllowCredentials(true); config.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }仅使用控制器注解:
保留@CrossOrigin,但补充允许OPTIONS方法和所有请求头:@CrossOrigin(origins = "*", allowedHeaders = "*", methods = {RequestMethod.PATCH, RequestMethod.OPTIONS}, maxAge = 3600)
2. 请求参数不匹配问题
后端用@RequestParam接收URL参数,但前端通过请求体(JSON)发送otp,导致后端无法获取参数,同时可能干扰CORS处理流程。
解决方式:
后端适配请求体:
创建DTO类接收JSON参数:public class OtpRequest { private String otp; public String getOtp() { return otp; } public void setOtp(String otp) { this.otp = otp; } }修改接口方法:
@PatchMapping("/verify") public ResponseEntity<?> authtotp(@RequestBody OtpRequest otpRequest) { userService.verifyAccount(otpRequest.getOtp()); return ResponseEntity.ok().build(); }前端适配URL参数:
修改axios请求,将otp放在URL参数中:axios.patch(`http://localhost:8080/api/users/verify?otp=${otp}`)
3. 前端错误处理优化
CORS失败时error.response为undefined,直接读取error.response.data会触发类型错误,需增加判断:
.catch(error => { let errorMsg = "Wrong OTP CODE!!"; if (!error.response) { errorMsg = "Verification request failed, please try again later"; console.error("Request failed:", error.message); } else { console.error("Error verifying OTP:", error.response.data?.error || "Unknown error"); } const msgElement = document.getElementById("verification-message"); msgElement.innerText = errorMsg; msgElement.style.color = "red"; });
内容的提问来源于stack exchange,提问作者C3ddyyy
相关产品推荐
相关产品推荐

