当前位置: 首页 > 科技观察

Web前端的“神秘”跨域方法

时间:2023-03-12 06:50:23 科技观察

什么是JavaScript跨域?出于安全原因,不允许跨域调用其他页面上的对象。那么什么是跨域呢?简单理解就是,由于JavaScript同源策略的限制,a.com域名下的js无法操作b.com或c.a.com域名下的对象。当协议、子域名、主域名、端口号中的任何一项不同时,都算作不同的域。不同域之间的资源请求被认为是“跨域”。有一点必须注意:跨域并不是说不能发送请求,可以发送请求,服务器可以正常接收请求并返回结果,只是结果被浏览器拦截了。跨域的原因是受同源策略的限制。同源策略要求同源才能正常通信,即协议、域名、端口号都完全相同。大家可以参考下图,帮助大家深入理解跨域。特别强调两点:***:如果是协议和端口导致的跨域问题,“前台”也无能为力。第二:在跨域问题上,域只是通过“URL的头部”来识别,不会根据域名对应的IP地址是否相同来判断。“URL的头部”可以理解为“协议、域名、端口必须匹配”。什么是同源策略及其限制同源策略限制从一个源加载的文档或脚本如何与另一个源的资源交互。这是隔离潜在恶意文件的关键安全机制。它的存在可以保护用户隐私信息,防止身份伪造等(阅读Cookie)。同源策略限制包括:Cookie、LocalStorage、IndexedDB等存储内容DOM节点不能发送AJAX请求,但是有3个标签允许跨域加载资源:下面我们来讨论如何处理跨域。但所有跨域都必须得到信息提供者的允许。如果可以不经许可获取,就是浏览器同源策略的漏洞。处理跨域方法一—JSONP1.JSONP原理利用标签,将跨域API数据接口地址赋值给脚本的src,并在该地址向服务器传递函数名(可以通过问号传递参数:?callback=fn)。服务端收到请求后,需要进行特殊处理:将传入的函数名和它需要给你的数据拼接成一个字符串,例如:传入的函数名是fn,准备好的数据是fn([{"姓名":"简书"}])。***服务端通过HTTP协议将准备好的数据返回给客户端,客户端调用并执行之前声明的回调函数(fn)对返回的数据进行操作。其中,fn是客户端注册的回调函数,目的是在跨域服务器上获取到json数据后,对数据进行处理。***服务端返回给客户端的数据格式为:5.jQuery的jsonp格式JSONP是GET和异步请求,没有其他请求方式和同步请求,jQuery会为JSONP请求清除缓存默认。处理跨域方法2——CORS1。CORS原理整个CORS通信过程由浏览器自动完成,无需用户参与。对于开发者来说,CORS通信和同源AJAX通信没有区别,代码完全一样。浏览器一旦发现AJAX请求是跨域的,就会自动添加一些额外的header信息,有时会有额外的请求,但是用户是感觉不到的。因此,实现CORS通信的关键是服务器。只要服务端实现了CORS接口,就可以实现跨域通信。2.CORS优缺点CORS需要浏览器(>IE10)和服务器同时支持。是跨域的根本解决方案,由浏览器自动完成。优点是功能比较强大,支持各种HTTP方式,缺点是兼容性不如JSONP。只需要在服务器端做一些小的修改:例如:网站http://localhost:{{63342:0}}/页面需要请求http://localhost:3000/users/userlist页面,userlist页面返回json字符串格式{name:'Mr.Cao',gender:'male',career:'ITEducation'}在响应头添加Access-Control-Allow-Origin属性指定地址同源政策。同源策略默认地址是网页本身。只要浏览器检测到响应头被CORS覆盖,并且允许的来源包括本网站,请求响应就不会被拦截。处理跨域方法三——WebSocketWebsocket是HTML5的持久化协议,实现了浏览器与服务器的全双工通信,也是一种跨域解决方案。WebSocket和HTTP都是应用层协议,都是基于TCP协议。然而,WebSocket是一种双向通信协议。连接建立后,WebSocket的服务端和客户端都可以主动向对方发送或接收数据。同时WebSocket在建立连接时需要使用HTTP协议。连接建立后,客户端与服务器的双向通信就与HTTP无关了。原生的WebSocketAPI使用起来不是很方便。我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单灵活的接口,同时为不支持webSocket的浏览器提供了向后兼容性。处理跨域方法四——postMessage如果两个网页来源不同,则无法获取到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,不能和父窗口通信。为了解决这个问题,HTML5引入了一个全新的API:跨文档消息传递API(Cross-documentmessaging)。该API为window对象添加window.postMessage方法,允许跨窗口通信,而不管两个窗口是否同源。postMessage方法的第一个参数是具体的消息内容,第二个参数是接收消息的窗口的来源(origin),即“协议+域名+端口”。也可以设置为*,表示不限制域名,发送给所有窗口。接下来我们来看一个例子: