温馨提示×

温馨提示×

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

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

SpringBoot怎么解决跨域

发布时间:2021-06-28 10:44:33 来源:亿速云 阅读:209 作者:小新 栏目:开发技术
# SpringBoot怎么解决跨域 ## 一、什么是跨域问题 ### 1.1 跨域的定义 跨域(Cross-Origin)是指浏览器出于安全考虑,限制网页脚本向不同源(协议+域名+端口)的服务发起HTTP请求。这是浏览器的同源策略(Same-Origin Policy)导致的限制。 ### 1.2 同源策略详解 同源策略要求以下三个必须相同: - 协议(http/https) - 域名(www.example.com) - 端口(80/443) 示例对比: | 当前URL | 请求URL | 是否同源 | 原因 | |---------|---------|---------|------| | http://a.com | http://a.com/api | 是 | 仅路径不同 | | https://a.com | http://a.com | 否 | 协议不同 | | http://a.com:8080 | http://a.com | 否 | 端口不同 | ### 1.3 跨域的常见场景 1. 前后端分离开发时,前端域名与API服务域名不同 2. 调用第三方API服务 3. 微服务架构中服务间调用 ## 二、SpringBoot解决跨域的5种方案 ### 2.1 使用@CrossOrigin注解 #### 2.1.1 方法级配置 ```java @RestController @RequestMapping("/api") public class MyController { @CrossOrigin @GetMapping("/users") public List<User> getUsers() { // ... } } 

2.1.2 类级配置

@CrossOrigin(origins = "http://localhost:3000", maxAge = 3600, allowedHeaders = {"Content-Type","Authorization"}) @RestController @RequestMapping("/api") public class MyController { // 所有方法都支持跨域 } 

2.1.3 参数说明

参数 说明 示例值
origins 允许的源 http://a.com”
methods 允许的HTTP方法 {RequestMethod.GET, RequestMethod.POST}
allowedHeaders 允许的请求头 {“Content-Type”,“X-Token”}
exposedHeaders 暴露的响应头 {“X-Custom-Header”}
maxAge 预检请求缓存时间(秒) 1800

2.2 全局CORS配置

2.2.1 WebMvcConfigurer方式

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } } 

2.2.2 Filter方式

@Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://localhost:3000"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); config.setMaxAge(3600L); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } 

2.3 使用Nginx反向代理

2.3.1 Nginx配置示例

server { listen 80; server_name api.example.com; location / { proxy_pass http://localhost:8080; # CORS headers add_header 'Access-Control-Allow-Origin' '$http_origin' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; # 处理OPTIONS预检请求 if ($request_method = 'OPTIONS') { return 204; } } } 

2.4 使用Spring Security配置CORS

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and() .authorizeRequests() // 其他安全配置... .anyRequest().authenticated(); } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000")); configuration.setAllowedMethods(Arrays.asList("GET","POST")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } } 

2.5 自定义Filter处理

@Component public class SimpleCORSFilter implements Filter { 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, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); chain.doFilter(req, res); } // 其他Filter方法... } 

三、跨域相关技术细节

3.1 预检请求(Preflight Request)

当请求满足以下条件时,浏览器会先发送OPTIONS预检请求: 1. 使用PUT、DELETE等非简单方法 2. 设置了自定义请求头 3. Content-Type不是以下三种: - text/plain - multipart/form-data - application/x-www-form-urlencoded

3.2 常见响应头说明

响应头 说明 示例值
Access-Control-Allow-Origin 允许的源 * 或 http://a.com
Access-Control-Allow-Methods 允许的方法 GET, POST, OPTIONS
Access-Control-Allow-Headers 允许的请求头 Content-Type, X-Token
Access-Control-Expose-Headers 暴露的响应头 X-Custom-Header
Access-Control-Max-Age 预检请求缓存时间 86400
Access-Control-Allow-Credentials 是否允许发送cookie true

3.3 带凭证的请求

当需要发送cookie或认证信息时: 1. 前端需要设置withCredentials: true 2. 服务端必须: - 指定具体域名(不能是*) - 设置Access-Control-Allow-Credentials: true

axios.get('http://api.example.com/data', { withCredentials: true }); 

四、方案对比与选型建议

4.1 各方案对比表

方案 适用场景 优点 缺点
@CrossOrigin 简单项目/特定接口 配置简单 不适合复杂配置
全局CORS配置 大多数SpringBoot项目 统一管理 需要理解配置项
Nginx代理 生产环境部署 性能好,统一入口 需要运维知识
Spring Security 已使用Security的项目 与认证集成 配置较复杂
自定义Filter 需要高度定制 完全控制流程 需要手动处理细节

4.2 选型建议

  1. 开发环境:使用@CrossOrigin或全局CORS配置
  2. 生产环境:推荐Nginx反向代理+SpringBoot基础CORS配置
  3. 需要精细控制:结合Spring Security配置
  4. 特殊需求:考虑自定义Filter

五、常见问题排查

5.1 跨域配置不生效的可能原因

  1. 配置顺序问题(Spring Security的配置可能覆盖其他CORS配置)
  2. 使用了多个CORS配置导致冲突
  3. 浏览器缓存了旧的CORS响应头
  4. 没有正确处理OPTIONS预检请求

5.2 调试技巧

  1. 使用Chrome开发者工具查看Network中的请求头
  2. 确认OPTIONS请求是否返回正确的CORS头
  3. 服务端日志检查是否收到请求
  4. 逐步简化配置定位问题

六、最佳实践

  1. 生产环境不要使用allowedOrigins("*"):应该明确指定允许的域名
  2. 合理设置maxAge:根据业务场景设置合适的缓存时间
  3. 严格限制允许的HTTP方法:按需开放,不要简单使用allowedMethods("*")
  4. 敏感接口添加额外保护:即使配置了CORS,重要接口仍需要身份验证
  5. 使用环境变量管理配置:不同环境(dev/test/prod)使用不同的CORS配置

七、总结

SpringBoot提供了多种灵活的跨域解决方案,开发者可以根据项目需求选择合适的方式。理解CORS的工作原理和浏览器行为对于正确配置至关重要。在安全性和便利性之间需要做好平衡,特别是在生产环境中要谨慎配置。

随着前端技术的发展,跨域问题会持续存在,但通过合理的架构设计(如API网关、微服务聚合层)可以减少前端直接面对跨域问题的机会。掌握这些解决方案将帮助开发者构建更健壮的Web应用系统。 “`

这篇文章共计约3900字,包含了: 1. 跨域问题的原理说明 2. 5种解决方案及代码示例 3. 技术细节和最佳实践 4. 方案对比和选型建议 5. 常见问题排查方法

格式采用标准的Markdown语法,包含代码块、表格、列表等元素,可以直接用于技术文档发布。

向AI问一下细节

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

AI