前言
什么是跨域:
- 跨域:即
浏览器请求域名与Ajax请求的域名不一致
。它是由浏览器的同源策略
造成的,是浏览器的一种安全机制
! - 同源策略:域名、协议、端口均相同。
- 场景:一般浏览器发送Ajax请求的使用经常遇到,由于浏览器同源策略的限制,导致无法接收到响应结果。
解决方案
有以下五种方案但不限于:
- JSONP
- CORS
- HttpClient内部转发
- Nginx接口网关*
- SpringCloud Zuul接口网关*
1. 使用JSONP(仅支持Get)
利用了使用src引用静态资源时不受跨域限制的机制。主要在客户端搞一个回调做一些参数接收与操作的处理,并把这个回调函数告知服务器,而服务器端需要做的是按照JavaScript的语法把数据放到约定好的回调函数之中即可,jQuery很早之前就已经把JSONP语法糖化了,使用起来会更加方便.。
原理:一般的 ajax是不能进行跨域请求的,但 img、iframe 、script等标签是个例外,这些标签可以通过 src属性请求到其他服务器上的数据,JSONP(json with padding 填充式json)方式我们的请求会JQuery被转换Script标签方式发出,并带有一个随机参数,需要服务端的配合,将随机参数一并返回。
$.ajax({
url: 'http://192.168.1.114/yii/demos/test.php', //不同的域
type: 'GET', // jsonp模式只有GET 是合法的
data: {
'action': 'aaron'
},
dataType: 'jsonp', // 数据类型
jsonp: 'backfunc', // 指定回调函数名,与服务器端接收的一致,并回传回来
})
JQuery内部转换成:
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron
然后动态加载:
<script type="text/javascript"src="http://192.168.1.114/yii/demos/test.php?backfunc= jQuery2030038573939353227615_1402643146875&action=aaron"></script>
参考博客:https://www.cnblogs.com/wqhwe/p/5816941.html
2. CORS 服务器端添加响应头(支持多种请求方式)
CORS(Cross-origin resource sharing 跨域资源共享),我们可以在服务端添加响应头Access-Control-Allow_Origin
,告诉浏览器允许访问,适用于小公司快速解决问题
response.setHeader("Access-Control-Allow_Origin","*"); // * 表示允许所有
3. 使用HttpClient内部转发
这种方式理解起来很容易,其实我们都知道同源策略是浏览器才有的一种机制。当我们需要发送跨域请求时,我们在服务端使用HttpClient发送请求,并把响应结果响应给客户端,这样就不存在跨域的问题了,客户端还是访问的本服务。
缺点:浪费资源,会发送两次请求
优点:安全,无法通过抓包分析
4. 使用Nginx搭建APi接口网关 (常用)
使用Nginx做反向代理,保证了域名端口一致,以新项目区分反向代理到的真实服务器地址。
修改nginx.conf配置文件,客户端访问,Nginx根据资源路径后缀转发到对应的服务。
5. 使用SpringCloud Zull接口网关 (常用)
Zuul核心配置如下:
# 配置网关反向代理,例如访问/api-member/** 直接重定向到member-service服务,实现路由转发,隐藏服务的真实ip(服务都实在内网中)
#zull根据服务名,去Eureka获取服务真实地址,并通过本地转发,而且默认开启Ribbon实现负载均衡
#默认读取Eureka注册列表 默认30秒间隔
zuul:
routes:
api-a: #会员服务网关配置
path: /api-member/** #访问只要是/api-member/ 开头的直接转发到member-service服务
#服务名
serviceId: member-service
api-b: #订单服务网关配置
path: /api-order/**
serviceId: order-service