一、跨域是什么?
跨域,指的是浏览器不能执行其他网站的脚本
当前页面的url 与 请求url的协议、域名、端口三个其中任意一个不同时都会产生跨域。
当前url | 请求的url | 是否跨域 | 跨域原因 |
---|---|---|---|
https://www.baidu.com | https://www.baidu.com/a.js | 否 | 同源 |
https://www.baidu.com | http://www.baidu.com/a.js | 是 | 协议不同,一个是https,一个是http |
https://www.baidu.com | https://www.baidu.com:8080/a.js | 是 | 端口号不同 |
https://www.baidu.com | https://www.test.com/a.js | 是 | 域名不同 |
二、为什么会有跨域
由于浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心和最基本的安全功能。web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的js脚本和另一个域的脚本进行交互。跨域限制访问,其实是浏览器的限制。
三、不同源的限制
- 无法读取不同源网页的cookie、localstorage、indexedDB
- 无法接触不同源网页的DOM
- 无法像不同源地址发送请求
四、前端开发常见跨域场景
前端开发过程中,在开发模式时,项目启动地址 和 部署在服务器上的数据接口地址 不同源,就会产生跨域,就会请求不到数据。
五、怎么解决跨域问题?
-
DOM层面和数据层面
1.1 设置document.domain解决无法读取非同源网页的 Cookie问题
document.domain是存放文档的服务器的主机名, 因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要 通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)// 两个页面都设置 document.domain = 'test.com';
1.2 跨文档通信 API:window.postMessage()
window.postMessage是HTML5新增的跨文档通信API,该API,允许跨窗口通信,不论这两个窗口是否同源。适合以下需求: - 页面和其打开的新窗口间数据传递 - 多窗口间消息传递 - 页面与嵌套的iframe消息传递 - 上面三个场景的跨域数据传递 //父页面向打开的新窗口发送消息 var openWindow = window.open('http://test.com', 'massage'); openWindow.postMessage('Nice to meet you!', 'http://test.com'); // 新窗口监听 message 消息 window.addEventListener('message', function (e) { console.log(e.source); // e.source 发送消息的窗口 console.log(e.origin); // e.origin 消息发向的网址 console.log(e.data); // e.data 发送的消息 },false);
1.3 window.name
浏览器窗口有window.name属性,这个属性的最大特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属 性,后一个网页可以读取它。如果需要实现父页面和跨域的子页面之间的通信,需要一个和父页面同源的子页面作为中介,将跨域的子页面中的信息传递过来。1.4 片段标识符
通过监听url中hash的改变来实现数据的传递//父页面 <div> <iframe src="./childHtml.html" id="childHtmlId"></iframe> </div> let ifraneDom = document.getElementById('childHtmlId') iframeDom.src += '#父传递给子' //子页面 window.onhashchange = function() { console.log(decodeURIComponent(window.location.hash)); };
-
网络层面
根据同源策略,浏览器默认是不允许XMLHttpRequest对象访问非同一站点的资源的,所以需要破解这种限制,实现跨域访问资源。目前主要采用以下几种方式。
1.代理
将请求代理到同源的服务器上,可以使用Nginx、Node中间件等
2.JSONP
JSONP借助script元素实现跨域技术,得益于script元素有这两种特点:src不受同源策略影响,能访问任何url资源;如果访问的资源包括js代码,会在下载后自动执行。
JSONP只支持get请求,网页通过添加一个< script >标签元素,像服务器请求JSON数据,服务器接收到请求后,将数据放在指定名字的回调函数参数位置传回来原生 <script src="http://website.com/getData?callback=getData"></script> 回调函数 <script type="text/javascript"> function getData(data){ //拿到数据 } </script> vueJs this.$http.jsonp('ttp://website.com/getData?callback=getData', { params: { }, jsonp: 'handleCallback' }).then(res => { //res )
3.CORS 方式
CORS (Cross-Origin Resource Sharing)1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin 2、带cookie跨域请求:前后端都需要进行设置 前端设置: 根据xhr.withCredentials字段判断是否带有cookie 服务端设置: 服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
参考文章
https://blog.csdn.net/qq_38128179/article/details/84956552
https://juejin.cn/post/6981008064543457294