前言:
上一篇的排版好难看,字体都不能设置,我们可不可以不悲伤——怎么可能
正文:
先复习一下jsonp,上图一张【源】
iFrame解决跨域
如果两个网页不同源,就无法拿到对方的DOM:iframe
窗口和window.open
方法打开的窗口,它们与父窗口无法通信
document.getElementById("myIFrame").contentWindow.document
// Uncaught DOMException: Blocked a frame from accessing a cross-origin frame.
window.parent.document.body
// 报错
1、如果两个窗口一级域名相同,二级域名不同,设置document.domain拿到DOM(共享cookie)
A网页是http://w1.example.com/a.html
,B网页是http://w2.example.com/b.html
,那么只要script中设置相同的document.domain
,两个网页就可以共享Cookie、拿到DOM
document.domain = 'example.com';
A通过脚本设置cookie:document.cookie = "test1=hello";B可以读到var allCookie = document.cookie;
对应完全不同源的网站,三种方法,解决:
1、片段识别符fragment identifier
fragment identifier指URL的#后部分,只是改变片段标识符,页面不会刷新
父窗体将信息写入子窗口的片段标识符:
var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;
子窗口监听hashchange得到通知:
window.onhashchange = checkMessage;
function checkMessage() {
var message = window.location.hash;
// ...
}
同样,子窗口可改变父窗口的片段标识符:
parent.location.href= target + "#" + hash;
这个博客有更详细的介绍 boystar iFrame跨域解决办法 https://www.cnblogs.com/boystar/p/6909214.html
window.name:全局window对象的属性
无论是否同源,只要在同一个窗口里,前一个网页设置这个属性,后一个网页可以读取它:
当iframe中加载新页面时,name属性值不变
仅同域名的iframe可访问; 数据量大:2M 安全 多种数据格式
父窗口先打开子窗口,载入不同源的网页,该网页将信息写入window.name
window.name=data
接着,子窗口跳回一个与主窗口同域的网址:
location=‘http://parent.url.com/xxx.html’
主窗口可以读取子窗口的window.name
var data = document.getElementById('myFrame').contentWindow.name;
window.postMessage:HTML5
跨文档通信API cross document messaging,为window对象新增window.postMessage方法,容许窗口通信、不论是否同源
父窗口http://aaa.com
向子窗口http://bbb.com
发消息,调用postMessage
var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');
第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*
,表示不限制域名,向所有窗口发送;
子窗口向父窗口发送消息的写法类似
window.opener.postMessage('Nice to see you', 'http://aaa.com');
通过message
事件,监听对方的消息:
window.addEventListener('message', function(e) {
console.log(e.data);
},false);
window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
//属性引用父窗口,发送消息
event.source.postMessage('Nice to see you!', '*');
}
//event.origin属性过滤不是发给本窗口的消息
window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
if (event.origin !== 'http://aaa.com') return;
if (event.data === 'Hello World') {
event.source.postMessage('Hello', event.origin);
} else {
console.log(event.data);
}
}
localStorage:借助上、读取其他窗口的localstorage
window.onmessage = function(e) {
if (e.origin !== 'http://bbb.com') {
return;
}
var payload = JSON.parse(e.data);
//子窗口将父窗口发来的消息,写入自己的LocalStorage
localStorage.setItem(payload.key, JSON.stringify(payload.data));
};
webSocket:通信协议
使用ws://和wss://(加密)作为协议前缀,只要服务器支持,跨源通信
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com//请求源(origin),哪个域名
nginx配置:
server{
# 监听9099端口
listen 9099;
# 域名是localhost
server_name localhost;
#凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871
location ^~ /api {
proxy_pass http://localhost:9871;
}
}
服务端处理跨域流程
兜兜转转到这里,后端@CrossOrigin、filter、还有一个全局的配置宝宝都试了,无效
jsonp需要服务器端支持,起码返回值前要加个callback吧,然鹅笨宝动不了服务端,见都没有见过,只是调一下貌似没有必要见,虽然我挺想见的,估计不难,iframe吧也不行,我不是要父子交互而是类似窗体跳转的效果,点击授权弹出成功登录界面,想想还有什么,jsonp!~已经pass了,nginx、调方法的是遇到了跨域,勉强跨域接收,这个耗了偶太长时间,要放弃时,猜、我看到了什么!
为什么form表单提交没有跨域问题,但ajax提交有跨域问题?
我的天、竟然这样,试试吧、你猜、竟然可以了!!!果然转发的好运微博没白转啊,哈哈~三个叹号都不足以表达我的心情,为什么一开始就完美地错过了呐?还是见识少的原因啊
ajax跨域是因为浏览器需要保护用户的安全和隐私而给js设定的限制
原页面form提交到另一个域名后,它的脚本无法获取新页面内容,不会把结果返回给js,浏览器认为是安全的:给别人发请求不拿数据;
而ajax可以读取响应的内容,浏览器不容许这样做:请求发出去了,但是响应数据被浏览器截取;
王宁博 跨域的那些事儿 这篇也不错
写Bug 不要再问我跨域的问题了 https://segmentfault.com/a/1190000015597029
阮一峰 浏览器同源政策及其规避方法 :http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
LLeo小浩 一篇文章可以解决跨域 https://www.imooc.com/article/19869?block_id=tuijian_wz 最后这个霸气的图的发源地,上篇简单请求的导图也盗于此