目录
前言
一、跨域
1、跨域的产生
二、解决跨域
1、具备src的标签
2、JSONP
3、CORS
4、WebSocket 协议(★★★★★)
(1)、WebSocket 协议的特点
(2)、WebSocket 协议客户端的 API
5、postMessage(★★★★★)
6、location.hash
7、document.domain
8、window.name
三、其他
1、反向代理
2、只针对Chrome的跨域解决办法
(1)、windows 操作系统
(2)、MAC OS 操作系统
四、对跨域的进一步学习
五、特殊的跨域
一篇优秀的文章:JavaScript学习总结(二)——延迟对象、跨域、模板引擎、弹出层、AJAX示例 - 张果 - 博客园
同源策略:同协议、同域名、同端口。
同源策略限制以下几种行为:
不遵守同源策略的通信就会产生跨域。
原理:所有具有src
属性的HTML标签都是可以跨域的
在浏览器中,、
、
和
这几个标签是可以加载跨域(非同源)的资源的,并且加载的方式其实相当于一次普通的GET请求,唯一不同的是,为了安全起见,浏览器不允许这种方式下对加载到的资源的读写操作,而只能使用标签本身应当具备的能力(比如脚本执行、样式应用等等)。
JSONP(JSON with padding,填充式 JSON 或参数式 JSON)看起来与 JSON 差不多,只不过是被包含在函数调用中的 JSON。
callback({"name": "value"});
JSONP 由两部分组成:回调函数 和 数据。回调函数是当响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。下面是一个典型的 JSONP 请求:
http://freetest.net/json/?callback=handleResponse
JSONP 的原理是:动态插入
(2)、b.html:(http://www.domain2.com/b.html) (3)、c.html:(http://www.domain1.com/c.html) 此方案仅限主域相同,子域不同的跨域应用场景。 实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。 (1)、父窗口:(http://www.domain.com/a.html) (2)、子窗口:(http://child.domain.com/b.html) window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。 (1)、a.html:(http://www.domain1.com/a.html) (2)、proxy.html:(http://www.domain1.com/proxy.... (3)、b.html:(http://www.domain2.com/b.html) 总结:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。 反向代理的原理:受同源策略的限制,非同源的通信就会产生跨域,导致客户端直接与服务器通讯失败,于是另辟蹊径,可以在本地配置一个服务器(我自测采用的是Wampserver(PHP+Apache)),配置好反向代理后,直接访问本地服务器,本地服务器会去访问远程服务器,服务期间的通信没有跨域,所以就绕开了跨域,借助本地服务器成功返回了数据。 反向代理学习资源大全:js的反向代理 - 腾讯云开发者社区 - 腾讯云 允许Chrome读写一个特定的文件夹。 ①、打开任务管理器,确保里面没有chrome 进程 ②、右键谷歌浏览器,"属性"中打开文件所在位置,进入浏览器安装文件夹 ③、在文件位置栏中启动cmd命令行,输入chrome.exe,确定是否能启动浏览器。如果不能请检查自己浏览器文件的路径是否正确 ④、 然后关掉chrome浏览器,通过在命令行输入chrome.exe --disable-web-security --user-data-dir 或 chrome.exe --args --disable-web-security --user-data-dir。 ⑤、将指令“ --disable-web-security --user-data-dir” 或 “ --args --disable-web-security --user-data-dir”粘贴到这条下图的目标中,注意有空格,这两种方式都是一样的,直接粘贴这种其实就相当于系统打开谷歌时执行了“目标”里的指令而已。 1⃣️、允许Chrome读写一个文件夹,比如:CCD。 新建一个文件夹,作为允许chrome读写的文件夹,查看其路径。 在terminal里运行以下命令: 命令执行后,弹出窗口,提示如下图: 点击启动即可开启一个新的网页,该网页已经可以读写CCD文件夹了。 2⃣️、解决302报错 再运行项目,可能会报错302(资源被重定向找不到了),怎么办呢? 在浏览器地址栏输入并访问下面的网址: ctrl+F 搜索:same-site-by-default-cookies,并将其设置为 disabled(禁用)。 最后别忘了点击 relaunch哦。 请戳此链接:https://segmentfault.com/a/1190000011145364 首先抛出一个问题:在本地访问本机起的服务会产生跨域吗? 答案是会的。下面我就来还原一下这个问题。 比如:我的 IP 地址是 192.168.x.x,我的端口号是 8080,起的服务的端口号是 8181。 目标接口是:http://192.168.x.x:8080/getData。 我前端页面访问的 URL 是:http://192.168.x.x:8080/home。 所以,我做了代理(本案例用的是 vue2): 代理后,我要访问的接口会变为:http://192.168.x.x:8181/api/getData。 这样做是正确的,没问题。但是,如果我前端页面访问的 URL 改为:http://localhost:8080/home,会发生什么?产生跨域了。至此,问题还原了。这是为什么呢? 这是因为 localhost 与 192.168.x.x 是不同的,localhost 不会被 DNS 解析为本机 IP 地址,那么显然这违反了 “同源策略” 的 “同域名” 的原则了,所以就会产生跨域了。
7、document.domain
8、window.name
var proxy = function(url, callback) {
var state = 0;
var iframe = document.createElement('iframe');
// 加载跨域页面
iframe.src = url;
// onload事件会触发2次,第1次加载跨域页,并留存数据于window.name
iframe.onload = function() {
if (state === 1) {
// 第2次onload(同域proxy页)成功后,读取同域window.name中数据
callback(iframe.contentWindow.name);
destoryFrame();
} else if (state === 0) {
// 第1次onload(跨域页)成功后,切换到同域代理页面
iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
state = 1;
}
};
document.body.appendChild(iframe);
// 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)
function destoryFrame() {
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
}
};
// 请求跨域b页面数据
proxy('http://www.domain2.com/b.html', function(data){
alert(data);
});
中间代理页,与a.html同域,内容为空即可。三、其他
1、反向代理
2、只针对Chrome的跨域解决办法
(1)、windows 操作系统
(2)、MAC OS 操作系统
open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=刚刚新建的文件夹的路径(我的是/Users/CCD)
// chrome 浏览器的某些实验功能
chrome://flags/
四、对跨域的进一步学习
五、特殊的跨域
module.exports = defineConfig({
DevServer: {
port: 8080,
hot: true,
proxy: {
'/api': {
target: "http://192.168.x.x:8181",
ws: false,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
})