CORS(跨域)工作原理
详细介绍参考:
总结起来就是:当浏览器发起 ajax 请求时,如果目标服务器和当前页面不在同一个域名下,那么将无法访问。
如果要支持跨域调用,那么需要浏览器和服务器同时配合:
- 浏览器请求时添加请求头
- Origin 跨域请求的原始域
- Access-Control-Request-Method 跨域请求的方式(如GET/POST)
- Access-Control-Request-Headers 跨域请求的请求头信息
浏览器发起跨域请求时,会自动添加请求头,不需要手动处理。
- 服务器返回时添加响应头
- Access-Control-Allow-Origin 允许跨域请求的原始域
- Access-Control-Allow-Credentials 是否允许客户端获取用户凭据(布尔类型)
- Access-Control-Allow-Methods 允许跨域请求的 http 方法(例如只授权GET/POST)
- Access-Control-Allow-Headers 允许跨域请求的请求头
- Access-Control-Expose-Headers 表示暴露哪些头部信息,并提供给客户端。(因为基于安全考虑,如果没有设置额外的暴露,跨域的通信对象XMLHttpRequest只能获取标准的头部信息)
- Access-Control-Max-Age 表示预检请求 [Preflight Request] 的最大缓存时间。(预检请求参考前文阮一峰的文章:非简单请求)
浏览器根据服务器的响应头判断是否允许跨域访问。
CORS 实现
SpringBoot
- 方式1:返回新的CorsFilter
- 方式2:重写WebMvcConfigurer
- 方式3:使用注解(@CrossOrigin)
- 方式4:手工设置响应头(HttpServletResponse )
具体参照前文链接。
Spring Cloud Gateway
在微服务架构下,我们除了可以在每个微服务内单独设置外,还可以在API网关全局设置跨域支持。
在 Spring Cloud Gateway 的yml配置文件添加配置
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedHeaders: "*"
allowedMethods: "*"
allowCredentials: true
坑
有一次我们系统需要开启跨域支持,用前文的方式配置完成后,用 postman 测试,无论采用哪种方式配置,竟然都没有响应头返回。在我一度怀疑是 Spring bug 的时候,鬼使神差的在 postman 的加了 Origin 请求头,竟然就好使了。 后来查看了是spring 源码,其内部会先判断当前请求是否跨域请求,只有跨域请求才会执行添加响应头相关的代码逻辑。