在 Java 后端开发中,跨域问题(CORS,Cross-Origin Resource Sharing)是由于浏览器的同源策略限制,当请求的协议、域名或端口与当前页面不一致时,浏览器会阻止该请求。为解决此问题,Java 提供了多种主流方案,适用于不同框架和场景。
主流解决方案
-
CORS(跨域资源共享):最常用、标准的解决方案,通过设置 HTTP 响应头实现。
-
JSONP:仅支持 GET 请求,适用于老旧系统,但安全性较低,已逐渐淘汰。
-
代理服务器:如 Nginx 或 Spring Cloud Gateway,将请求转发至目标服务,绕过浏览器限制。
-
手动设置响应头:在每个控制器方法中添加 CORS 头,适用于简单场景但维护成本高。
常用实现方式(按场景分类)
- Spring Boot 项目推荐方式
- 全局配置(推荐):适用于整个应用统一处理跨域。
```java
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*"); // 允许所有源,生产环境应指定具体域名
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true); // 允许携带凭证(如 Cookie)
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
```
- 局部注解(@CrossOrigin):适用于个别接口或控制器。
```java
@RestController
@CrossOrigin(origins = "http://localhost:3000") // 指定允许的源
@RequestMapping("/api")
public class DataController {
@GetMapping("/data")
public String getData() {
return "Cross-origin data";
}
}
```
- WebMvcConfigurer 配置(Spring MVC 4.2+):
```java
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
```
- 非 Spring 项目(原生 Java Web)
使用 Servlet Filter 拦截所有请求并添加 CORS 头:
```java
@WebFilter("/*")
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
}
```
- 使用 Nginx 反向代理(前端/服务端通用)
在 Nginx 配置中添加 CORS 头并代理请求:
```nginx
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
return 204;
}
proxy_pass http://localhost:8080; 后端 Java 服务地址
}
```
安全注意事项
-
生产环境避免使用 `Access-Control-Allow-Origin: *`,应明确指定允许的域名。
-
若需携带凭证(如 Cookie),不能设置 `*`,必须指定具体源,例如:
```java
config.addAllowedOrigin("http://localhost:3000");
config.setAllowCredentials(true);
```
- 限制 `allowedMethods` 和 `allowedHeaders`,仅开放必要权限。
参考资料
-
阿里云开发者社区:Java 中处理跨域请求的方法\](https://developer.aliyun.com/article/1555356)
-
CSDN:Java 配置跨域(CORS)\](https://blog.csdn.net/weixin_67327688/article/details/150769454)