CORS跨域
1.跨域问题
1.1.什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
当前页面url | 被请求页面url | 是否跨域 | 原因 |
---|---|---|---|
http://www.test.com/ | http://www.test.com/index.html | 否 | 同源(协议、域名、端口号相同) |
http://www.test.com/ | https://www.test.com/index.html | 跨域 | 协议不同(http/https) |
http://www.test.com/ | http://www.baidu.com/ | 跨域 | 主域名不同(test/baidu) |
http://www.test.com/ | http://blog.test.com/ | 跨域 | 子域名不同(www/blog) |
http://www.test.com:8080/ | http://www.test.com:7001/ | 跨域 | 端口号不同(8080/7001) |
上述表格出自播客:https://blog.csdn.net/qq_38128179/article/details/84956552
比如是从manage.test.com
去访问api.test.com
,这属于三级域名不同,跨域了。
1.2.为什么有跨域问题?
跨域不一定会有跨域问题。
因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是于当前页同域名的路径,这能有效的阻止跨站攻击。
因此:跨域问题 是针对ajax的一种限制。
但是这却给我们的开发带来了不变,而且在实际生成环境中,肯定会有很多台服务器之间交互,地址和端口都可能不同,怎么办?
1.3.解决跨域问题的方案
浏览器虽然会限制跨域请求,但是也给出了解决方案。如果你确实需要发送跨域的ajax,必须通过被访问的服务端同意才可以。
浏览器与服务器间协商是否允许跨域,这样的方式就是CORS。
参考文档:https://www.ruanyifeng.com/blog/2016/04/cors.html
2.CORS介绍
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
-
浏览器端:
目前,所有浏览器都支持该功能(IE10以下不行)。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。浏览器会在发出ajax时询问服务端是否允许当前网站的跨域请求,并根据服务端响应做出拦截或放行的处理。
-
服务端:
CORS通信与AJAX没有任何差别,因此你不需要改变以前的业务逻辑。只不过,浏览器会在请求中携带一些头信息,表明请求者的身份。服务端接收到以后,需要对这些信息做出判断,如果允许则需要在返回的头信息中携带一些许可的声明。
3.SpringCloudGateway的CORS
在SpringCloudGateway中,已经提供了默认的CORS实现,我们只需要通过application.yml做简单配置即可。
spring:
cloud:
gateway:
# 。。。
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 是否将当前cors配置加入到SimpleUrlHandlerMapping中,解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://manage.test.com"
- "http://www.test.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
完整配置:
server:
port: 10010
eureka:
client:
service-url:
defaultZone: http://test-registry:10086/eureka
hystrix:
command:
default:
execution.isolation.thread.timeoutInMilliseconds: 6000 # 熔断超时时长:6000ms
ribbon:
ConnectTimeout: 500 # ribbon链接超时时长
ReadTimeout: 2000 # ribbon读取超时时长
spring:
application:
name: test-gateway
redis:
host: test-redis # redis地址
port: 6379 # redis端口
cloud:
gateway:
default-filters: # 默认过滤项
- StripPrefix=1 # 去除路由前缀
- name: Hystrix # 指定过滤工厂名称(可以是任意过滤工厂类型)
args: # 指定过滤的参数
name: fallbackcmd # hystrix的指令名
fallbackUri: forward:/hystrix/fallback # 失败后的跳转路径
- name: RequestRateLimiter #请求数限流 名字不能随便写
args:
key-resolver: "#{@ipKeyResolver}" # 通过spEL表达式指定一个key生成器,#{}是spEL,@代表spring中的Bean
redis-rate-limiter.replenishRate: 2 # 生成令牌的速率
redis-rate-limiter.burstCapacity: 2 # 桶的容量
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 是否将当前cors配置加入到SimpleUrlHandlerMapping中,解决options请求被拦截问题
corsConfigurations:
'[/**]': # /** 代表拦截一切请求路径,都需要做CORS判断
allowedOrigins: # 允许哪些网站的跨域请求
- "http://manage.test.com"
- "http://www.test.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
routes:
- id: item-service # 商品微服务
uri: lb://item-service
predicates:
- Path=/item/**
logging:
level:
com.test: debug