怎么理解Spring Boot跨域

发布时间:2021-11-17 10:24:33 作者:iii
来源:亿速云 阅读:151
# 怎么理解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) - 前后端分离部署时的域名差异

二、Spring Boot解决跨域的四种方式

2.1 使用@CrossOrigin注解

最简单的局部解决方案,支持方法级和类级配置:

@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等)

2.2 实现WebMvcConfigurer(全局配置)

推荐的生产环境方案,通过配置类统一管理:

@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使用

2.3 使用Filter手动设置响应头

适用于需要精细控制的场景:

@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:是否允许凭据

2.4 结合Spring Security配置

当项目启用安全模块时,需要特殊处理:

@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的冲突

三、深入理解CORS机制

3.1 简单请求 vs 预检请求

简单请求需同时满足: 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

3.2 完整CORS交互流程

  1. 浏览器发送OPTIONS预检请求
  2. 服务器响应允许的源/方法/头部
  3. 浏览器验证通过后发送真实请求
  4. 服务器返回实际数据+ CORS头部
sequenceDiagram
    Browser->>Server: OPTIONS /api (预检请求)
    Server-->>Browser: 返回Allowed-Origin/Methods/Headers
    Browser->>Server: GET /api (真实请求)
    Server-->>Browser: 数据 + CORS头

四、生产环境最佳实践

4.1 安全配置建议

  1. 不要盲目使用*:应明确指定可信域名 “`java // 不安全 .allowedOrigins(”*“)

// 安全做法 .allowedOrigins(”https://production.com”, “https://staging.com”)


2. **启用Credential时严格限制源**:
   ```java
   .allowCredentials(true)
   .allowedOrigins("https://exact.domain.com") // 不能使用*或通配符
  1. 限制暴露的头部
    
    .exposedHeaders("X-Custom-Header", "Content-Disposition")
    

4.2 常见问题排查

问题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

五、扩展:替代解决方案

5.1 反向代理方案

通过Nginx统一域名:

location /api {
    proxy_pass http://backend:8080;
    add_header 'Access-Control-Allow-Origin' '$http_origin' always;
}

5.2 JSONP(仅限GET请求)

传统跨域方案,已逐渐淘汰:

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需要单独配置
- 预检请求的缓存能提升性能 “`

推荐阅读:
  1. 一篇文章帮你理解什么是ajax跨域
  2. 如何解决Spring boot 和Vue开发中CORS跨域问题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spring boot

上一篇:java中事务的传播行为有哪些

下一篇:jquery如何获取tr里面有几个td

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》