浏览器的同源策略与跨域:
浏览器同源策略:
浏览器会限制对异源(异域)的资源操作
所谓同源是指:协议,端口,域名均相同
为什么要有浏览器的同源策略:
1.用户登录了网银,网银向用户的 cookie 中添加用户标识。
2.用户浏览了恶意页面,执行了恶意页面中的AJAX 请求代码。
3.恶意页面向网银发起 AJAX HTTP 请求,请求会默认把网银对应 cookie 也同时发送过去。
4.网银从发送的 cookie 中提取用户标识,验证用户无误,response 中返回请求数据。此时数据就泄露了。
调用第三方接口是跨域吗?
算跨域。但是接口提供方做了处理。处理方式是CORS
为什么postman调接口不会跨域而浏览器会 :
浏览器在真正发送请求前,会先发送一个Options请求嗅探,请求成功后才会发送真实的请求.而postman等工具调用接口时,只是简单的访问一个资源,并不存在资源的相互访问。
为什么需要发送预检请求?是因为触发了浏览器的安全校验。
为什么请求会触发安全校验?因为当前请求是一个"复杂请求"。
为什么我的请求是“复杂的”?
简单请求:请求方法是GET/HEAD/POST,并且contentType为text/plain、application/x-www-form-urlencoded、multipart/form-data。
不满足上述条件的视为复杂请求,开发中我们常触发这个条件大多因为我们的请求的contentType设置的是application/json导致的。
简单请求如果设置了Authentication认证header也会让请求“升级”为复杂请求。
模拟跨域:
我在localhost:8080下访问http://localhost/test/1.php,因为端口号不同,所以算作跨域(尽管返回200,但是数据是空)
跨域的解决方式:
1.CORS解决跨域问题
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而解决AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前基本上主流的浏览器都支持CORS。所以只要后端服务支持CORS,就能够实现跨域。
对于简单请求,我们后端直接header('Access-Control-Allow-Origin:*');就可以了
对于复杂请求
if request.method == 'OPTIONS':
# 告诉浏览器你发的非简单请求(修改了Content-type)我允许了
response['Access-Control-Allow-Headers'] ='Content-type
'# 告诉浏览器 你发送PUT请求我也支持
response['Access-Control-Allow-Methods'] ='PUT, DELETE'
return response
2.jsonp:
利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP,这项技术可以解决跨域提交Ajax请求的问题。
缺点:只能允许get
原生写法:
vue写法:
3.document.domain + iframe跨域
4.window.name + iframe跨域
5.location.hash + iframe跨域
6.postMessage跨域
7.nginx代理跨域
(1)nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。
location/ {add_headerAccess-Control-Allow-Origin *;}
(2)nginx反向代理接口跨域
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
8.Nodejs中间件代理跨域
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。
9.WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
ModifyHeaders(模拟请求头插件实现跨域)