您好,登录后才能下订单哦!
# 怎么理解Spring Boot跨域
## 一、什么是跨域问题
### 1.1 同源策略的概念
同源策略(Same-Origin Policy)是浏览器最核心的安全机制之一,它规定:
- 协议相同(http/https)
- 域名相同(www.example.com)
- 端口相同(8080)
只有三者完全一致才属于同源,否则就会触发跨域限制。这是浏览器为了防止恶意网站窃取数据而设置的安全屏障。
### 1.2 跨域的表现形式
当出现跨域请求时,浏览器控制台会显示类似错误:
```javascript
Access-Control-Allow-Origin' header is present on the requested resource
常见跨域场景包括: - 前端运行在http://localhost:3000,后端在http://localhost:8080 - 微服务架构中不同子域间的调用(api.service.com调用auth.service.com) - 前后端分离部署时的域名差异
最简单的局部解决方案,支持方法级和类级配置:
@RestController
@CrossOrigin(origins = "http://example.com") // 类级别
public class MyController {
@GetMapping("/hello")
@CrossOrigin( // 方法级别
origins = "*",
allowedHeaders = "*",
methods = {RequestMethod.GET, RequestMethod.POST}
)
public String hello() {
return "Hello World";
}
}
参数说明:
- origins
:允许的源列表(默认*)
- methods
:允许的HTTP方法
- allowedHeaders
:允许的请求头
- exposedHeaders
:暴露给客户端的响应头
- allowCredentials
:是否允许凭据(cookies等)
推荐的生产环境方案,通过配置类统一管理:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://trusted.com")
.allowedMethods("GET", "POST", "PUT")
.allowCredentials(true)
.maxAge(3600);
}
}
优势: - 统一管理所有端点的CORS策略 - 支持预检请求(OPTIONS)缓存 - 可结合Spring Security使用
适用于需要精细控制的场景:
@Component
public class SimpleCorsFilter 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", "POST, GET, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
chain.doFilter(req, res);
}
}
关键响应头:
- Access-Control-Allow-Origin
:允许的源
- Access-Control-Allow-Methods
:允许的方法
- Access-Control-Allow-Headers
:允许的请求头
- Access-Control-Expose-Headers
:暴露的响应头
- Access-Control-Allow-Credentials
:是否允许凭据
当项目启用安全模块时,需要特殊处理:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.applyPermitDefaultValues();
config.addAllowedOrigin("https://secure-domain.com");
return config;
});
// 其他安全配置...
}
}
注意事项:
- 必须显式调用http.cors()
- 默认会禁用allowCredentials
- 需要处理CSRF与CORS的冲突
简单请求需同时满足: 1. 使用GET、HEAD或POST方法 2. 仅包含自动设置的头部(如Accept、Content-Language) 3. Content-Type为:text/plain、multipart/form-data或application/x-www-form-urlencoded
预检请求(OPTIONS)触发条件: - 使用PUT、DELETE等非简单方法 - 包含自定义头部(如Authorization) - Content-Type为application/json
sequenceDiagram
Browser->>Server: OPTIONS /api (预检请求)
Server-->>Browser: 返回Allowed-Origin/Methods/Headers
Browser->>Server: GET /api (真实请求)
Server-->>Browser: 数据 + CORS头
*
:应明确指定可信域名
“`java
// 不安全
.allowedOrigins(”*“)// 安全做法 .allowedOrigins(”https://production.com”, “https://staging.com”)
2. **启用Credential时严格限制源**:
```java
.allowCredentials(true)
.allowedOrigins("https://exact.domain.com") // 不能使用*或通配符
.exposedHeaders("X-Custom-Header", "Content-Disposition")
问题1:配置了CORS但仍报错 - 检查是否有多个Filter覆盖了CORS头 - 确认Spring Security配置是否正确
问题2:预检请求返回403 - 确保OPTIONS方法被允许 - 在Spring Security中配置:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();
问题3:Cookie无法跨域
- 前端需要设置withCredentials: true
- 后端配置:
.allowCredentials(true)
.allowedOriginPatterns("https://*.domain.com") // 注意使用allowedOriginPatterns而非allowedOrigins
通过Nginx统一域名:
location /api {
proxy_pass http://backend:8080;
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
}
传统跨域方案,已逐渐淘汰:
function handleResponse(data) {
console.log(data);
}
const script = document.createElement('script');
script.src = 'http://other-domain.com/api?callback=handleResponse';
document.body.appendChild(script);
Spring Boot提供了多层次、灵活的跨域解决方案,开发者应根据: - 项目架构复杂度 - 安全要求级别 - 部署环境特点
选择最适合的方案。对于现代应用,推荐优先采用WebMvcConfigurer
全局配置,配合细致的域名/方法限制,在保证安全的前提下实现跨域资源共享。
关键点记忆:
- 开发环境可用*
,生产环境必须指定具体域名
- 带Credential的请求不能使用通配符
- Spring Security需要单独配置
- 预检请求的缓存能提升性能 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。