We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
浏览器有同源策略,只有当“协议”、“域名”、“端口号”都相同时,才能称之为是同源,其中有一个不同,即是跨域。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
同源策略限制内容有:
但是这里有个例外,所有带 src 属性的标签都可以跨域加载资源,不受同源策略的限制,同时这个特性也会被用作 CSRF 攻击。
src
CSRF
不同域之间相互请求资源,就算作“跨域”。
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。
尽管浏览器有同源策略,但是 <script> 标签的 src 属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。jsonp 通过插入 script 标签的方式来实现跨域,参数只能通过url传入,仅能支持get请求。
<script>
script
原理:利用<script>标签不受跨域限制,将回调函数名作为参数附带在请求中,服务器接受到请求后,进行特殊处理:把接收到的函数名和需要给它的数据拼接成一个字符串返回,客户端会调用相应声明的函数,对返回的数据进行处理。
优点:
缺点:
CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 ajax 只能同源使用的限制。 CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
XMLHttpRequest
先了解一下,请求分简单请求与复杂请求,复杂请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为 预检 请求,该请求是 option 方法的,通过该请求来知道服务端是否允许跨域请求。
预检
option
cors请求流程图:
优缺点:
POST
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
页面和其打开的新窗口的数据传递 多窗口之间消息传递 页面与嵌套的iframe消息传递 上面三个场景的跨域数据传递
postMessage() 方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
postMessage()
Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
实现原理:同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。 代理服务器,需要做以下几个步骤:
实现原理类似于Node中间件代理,需要搭建一个中转nginx服务器,用于转发请求。 使用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。
原理:
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。 只需要给页面添加 document.domain ='test.com' 表示二级域名都相同就可以实现跨域。 实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
withCredentials
axios.defaults.withCredentials=true
nginx配置:
Access-Control-Allow-Credentials
true
Access-Control-Allow-Origin
*
The text was updated successfully, but these errors were encountered:
https://mp.weixin.qq.com/s/umfvlTMcBVRGQfyO4iFNvg
Sorry, something went wrong.
No branches or pull requests
同源策略
浏览器有同源策略,只有当“协议”、“域名”、“端口号”都相同时,才能称之为是同源,其中有一个不同,即是跨域。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
同源策略限制内容有:
但是这里有个例外,所有带
src
属性的标签都可以跨域加载资源,不受同源策略的限制,同时这个特性也会被用作CSRF
攻击。跨域
不同域之间相互请求资源,就算作“跨域”。
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。
跨域的方法
1. jsonp
尽管浏览器有同源策略,但是
<script>
标签的src
属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。jsonp 通过插入script
标签的方式来实现跨域,参数只能通过url传入,仅能支持get请求。原理:利用<script>标签不受跨域限制,将回调函数名作为参数附带在请求中,服务器接受到请求后,进行特殊处理:把接收到的函数名和需要给它的数据拼接成一个字符串返回,客户端会调用相应声明的函数,对返回的数据进行处理。
优点:
缺点:
2. CORS
CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)它允许浏览器向跨源服务器,发出
XMLHttpRequest
请求,从而克服了 ajax 只能同源使用的限制。CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
先了解一下,请求分简单请求与复杂请求,复杂请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为
预检
请求,该请求是option
方法的,通过该请求来知道服务端是否允许跨域请求。cors请求流程图:
优缺点:
POST
请求方式3. postMessage
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
页面和其打开的新窗口的数据传递
多窗口之间消息传递
页面与嵌套的iframe消息传递
上面三个场景的跨域数据传递
postMessage()
方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。4. websocket
Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
5.Node中间件代理(两次跨域)
实现原理:同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。 代理服务器,需要做以下几个步骤:
6. nginx反向代理
实现原理类似于Node中间件代理,需要搭建一个中转nginx服务器,用于转发请求。
使用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。
原理:
7. window.name + iframe
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
8. location.hash + iframe
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
9. document.domain + iframe
该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。
只需要给页面添加 document.domain ='test.com' 表示二级域名都相同就可以实现跨域。
实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
跨域时cookie处理
客户端处理
withCredentials
axios.defaults.withCredentials=true
服务端处理
nginx配置:
Access-Control-Allow-Credentials
:可选字段。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true
,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true
,如果服务器不要浏览器发送 Cookie,删除该字段即可。Access-Control-Allow-Origin
的值为*
。这是因为请求的首部中携带了Cookie信息,如果Access-Control-Allow-Origin
的值为*
,请求将会失败。而将Access-Control-Allow-Origin
的值设置为 a.b.com,则请求将成功执行。也就是说Access-Control-Allow-Credentials
设置为true
的情况下Access-Control-Allow-Origin
不能设置为*
。参考资料
The text was updated successfully, but these errors were encountered: