跨域三种解决方式

核心提示前言前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容。一、什么是跨域?1.什么是同源策略及其限制内容?同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS

在数据交互前后,经常会遇到跨域请求,什么是跨域,有哪几种跨域方式,这些都是本文要讨论的内容。

1.什么是跨域?

1.什么是同源策略及其限制内容?

同源策略是一种协议,是浏览器最核心、最基本的安全功能。如果没有同源策略,浏览器很容易受到XSS、CSRF和其他攻击。所谓同源,就是“协议+域名+端口”相同,即使两个不同的域名指向同一个ip地址,也不是同源。

相同的源策略限制包括:

cookie、本地存储、索引数据库和其他存储内容

DOM节点

AJAX请求发送后,结果被浏览器截获。

但是有三个标签允许跨域加载资源:

//b . html window . on message = function { console . log//我爱你e.source.postMessage}

4 .网络插座

Websocket是HTML5的持久性协议,实现浏览器和服务器的全双工通信,也是一种跨域的解决方案。WebSocket和HTTP都是应用层协议,都是基于TCP协议。然而,WebSocket是一种双向通信协议。连接建立后,WebSocket的服务器端和客户端都可以主动向对方发送或接收数据。同时,WebSocket在建立连接时需要HTTP协议的帮助。连接建立后,客户端和服务器之间的双向通信与HTTP无关。

原生webSocket API使用起来不是很方便。我们使用Socket.io,它很好的封装了webSocket接口,提供了更简单灵活的接口,也为不支持WebSocket的浏览器提供了向后兼容性。

让我们先举一个例子:本地文件socket.html生成并接收来自localhost:3000的数据。

//socket.html

//server . jslet express = require;让app =快递;设WebSocket = require//记得安装wslet wss = new WebSocket。服务器;WSS . on { ws . on { console . log;ws . send });})

5.节点中间件代理

实现原理:同源策略是浏览器需要遵循的标准,但如果服务器请求服务器,则不必遵循同源策略。

代理,您需要做以下步骤:

接受客户端请求。

将请求转发给服务器。

获取服务器响应数据。

将响应转发给客户端。

我们举个例子:本地文件index.html文件通过代理服务器http://localhost:3000向目标服务器http://localhost:4000请求数据。

//index.html

// server1.js代理服务器const http = require//第一步:接受客户端请求const server = http . createserver = > {//代理服务器,直接与浏览器交互,设置CORS头字段response.writeHead //第二步:将请求转发到服务器const proxy request = http . requestserveresponse . on = > { console . log//第四步:将响应结果转发到浏览器response.end})}。end })server . listen = > { console . log })

//server 2 . js const http = require const data = { title:' font end ',password:' 123456 ' } const server = http . create server = > { if { response . end)} })server . listen = > { console . log })

上面的代码已经跨域两次。值得注意的是,浏览器向代理服务器发送请求,同样遵循同源策略。最后,它打印出index.html文件中的{"title": "fontend "," password": "123456"}。

6.nginx反向代理

实现原理类似于节点中间件代理,需要你构建一个中转nginx服务器来转发请求。

使用nginx反向代理跨域是最简单的跨域方式。只需要修改nginx的配置就可以解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,也不会影响服务器的性能。

实现思路:通过nginx配置一个代理服务器作为跳板,反向代理访问domain2接口,顺便修改cookie中的域信息,方便当前域cookie写入,实现跨域登录。

先下载nginx,然后修改nginx目录下的nginx.conf,如下:

//代理服务器server { listen 80服务器名www.domain1.com;location/{ proxy _ pass http://www.domain2.com:8080;#反向代理proxy _ cookie _ domain www.domain2.com www.domain1.com;#修改cookie中的域名索引index.html index.htm;#用webpack-dev-server等中间件代理接口访问nignx时,此时没有浏览器参与,所以没有同源限制。下列跨域配置不启用add _ header access-control-allow-origin http://www.domain1.com;#当前端只跨没有cookie的域时,可以是* add _ header access-control-allow-credentials true;}}

最后,通过命令行nginx -s reload启动nginx。

//index . html var xhr = new XMLHttpRequest;//前端开关:浏览器是否读写cookie cookiexhr . with credentials = true;//访问nginx中的代理服务器xhr.openxhr.send

//server . jsvar http = require;var server = http.createServervar qs = requireserver . on { var params = QS . parse);//将cookie res.writeHead写到前台;RES . write);res.end});server.listenconsole.log

window.name + iframe

window.name属性的唯一性:加载不同页面后名称值依然存在,可以支持很长的名称值。

A.html和b.html属于同一个域,都是http://localhost:3000;c.html是http://localhost:4000。

//a.html

B.html是中间代理页面,与a.html同域,内容为空。

//c.html

总结:跨域数据通过iframe的src属性从外地域转移到本地域,即通过iframe的window.name从外地域转移到本地域。这样巧妙地绕过了浏览器的跨域访问限制,但同时又是一种安全的操作。

location.hash + iframe

实现原理:a.html想要和c.html跨域通信,可以通过中间页面b.html实现。三个页面,不同的域使用iframe的location.hash传递值,相同的域通过直接js访问相互通信。

实现步骤:首先,a.html发送一个哈希值给a.html,然后a.html接收哈希值,然后发送给a.html,最后a.html将结果放入a . html的哈希值中。

同样,a.html和b.html在同一个域,都是http://localhost:3000;c.html是http://localhost:4000。

//a.html

//b.html

//c.html console . log;设iframe = document.createElementiframe . src = ' http://localhost:3000/b . html # idontloveyu ';document . body . appendchild;

9 .文档.域+ iframe

这种方法只能在二级域名相同的情况下使用,如a.test.com和b.test.com。

只需在页面中添加document.domain ='test.com '表示二级域名全部相同,即可实现跨域。

实现原理:两个页面都通过js强制设置document.domain为基本主域,从而实现同域。

我们来举个例子:页面a.zf1.cn:3000/a.html获取页面b.zf1.cn:3000/b.html.中A的值

//a.html你好

//b.html你好

三。摘要

CORS支持所有类型的HTTP请求,是跨域HTTP请求的基本解决方案。

JSONP只支持GET请求。JSONP的优点是支持旧浏览器,从不支持CORS的网站请求数据。

无论是节点中间件代理还是nginx反向代理,服务器主要通过同源策略不受限制。

在日常工作中,cors和nginx反向代理是广泛使用的跨域方案。

来自简书:前方三少爷原文链接:https://www.jianshu.com/p/2896288494df

 
友情链接
鄂ICP备19019357号-22