MDN Web Docs 中定义跨域,当一个资源从与该资源本身所在的服务器不同的域或端口不同的域或不同的端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
即访问了一个网站,然后在这个网站返回的资源里面,请求了B网站/端口的资源。
跨域这个情况只会出现在浏览器页面里,因为实际上是浏览器由于安全原因限制了这些请求的访问。
CSRF攻击,如果前端可以跨域,那:
用户访问A,生成cookie存储在本地,点击弹窗广告进入地址B,B网站可以在自己的页面中获取A的cookie,然后模拟用户登录
同源限制有:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) 请求的响应被拦截
在postman和APP里面,每发出一个请求,都是在独立请求一个资源,而不是在一个网站返回的页面里,再去请求另外一个网站/端口的资源。自然也就不会造成跨域了。
想要实现跨域主要是因为不会把所有资源放在一台服务器上。
回调和数据
动态创建script元素并为src属性指定跨域URL实现,script与img元素类似,src不受同源策略限制。相比img的图片探测,它可以实现双向通信。
类似JSONP只能get
window对象的name属性,标记打开的窗口,窗口中所有页面共用且始终存在。
新建iframe利用其src跨域请求资源,获得资源之后修改src与父页面同域。然后通过name属性共享资源。
跨域访问其实只是浏览器的同源策略,服务器没有这个限制
Node.js的http模块等都可以抓取其他网站的页面。
把前端Ajax需要跨域访问的地址交给后台服务器
Nginx
http代理服务、反向代理服务器(HTTP中间件)
正向代理:代理客户端发起请求。对客户端已知,对服务端透明(服务器不知道谁在访问)的代理应用,称为正向代理。如:梯子
反向代理:服务器内置几个服务器,用户去访问。
nginx反向代理处理请求实现跨域
解决前后端分离开发中,前端对接口联调中的跨域问题。
将nginx反向代理服务器部署在浏览器同源位置,在配置文件nginx.conf 中设置端口监听转发请求
过去,跨源或者窗口间通信需要通过服务器
window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,就可以安全地实现跨源通信。
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message
将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。
在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。
发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
所有跨域的js在提交请求的时候,如果服务端设置了可跨域访问需要分简单请求(simple request)和非简单请求(not-so-simple request)来处理。
简单请求:
HEAD
GET
部分POST(header:application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种)
而复杂请求
浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。
预检请求的服务器验证机制
这个请求通过使用OPTIONS方法发送并包含以下头部
Origin:
Access-Control-Request-Method:
Access-Control-Request-Header:
浏览器判断这是一个跨域请求之后,自动添加跨域请求配置的头信息。S端判断是否允许这个域访问
使用自定义的HTTP头部允许浏览器和服务器相互了解,以确定请求成功与否
这样的请求在发送的时候,会自动添加一个额外的头部Origin,包含发送请求的页面的源。
如果服务器决定响应请求,会发送Access-Control-Allow-Origin头部
出于安全考虑,跨域XHR对象也施加一些额外限制
凭据请求
默认情况下,跨域请求不提供凭证(cookie、HTTP认证和客户端SSL证书)
withCredentials属性=true来设置发送凭证
HTML5提出了 WebSocket库,同时Node.js后端使用ws模块支持。使用前需要确保浏览器是否支持。
HTTP是单向通信,只有客户端请求服务器端响应,但是websocket是双向的,双方都可以主动向对方发消息。
websocket需要HTTP协议来完成握手操作,握手结束之后,双方使用websocket协议通信,与HTTP再无关系。