关于img标签跨域的问题
1、PC端:因为img标签不是js,所以不能在请求图片地址的时候加请求头。
2、移动端:移动端不能记住请求的账号密码,所以移动端必须请求图片的时候发送请求头,这是一个很大问题。
PC端解决方案
解决思路:当请求存在跨域时,会弹出需要身份验证的对话框,输入一次账号密码后,再重新请求,就不会有对话框了,说明浏览器会记住账号密码,所以只要用ajax将账号密码发送请求就可以了。
1 | var url = 'http://10.10.2.111:8000/fcrepo/rest/msxAD/3202/201712214.png'; //跨域图片地址 |
移动端解决方案
参考地址:链接
解决思路:因为移动端不会弹出对话框,且不能保存账号密码,不能用ajax发送账号密码请求来解决。先将图片的跨域地址请求成功,然后img标签地址不要用跨域地址,而是用window.URL.createObjectURL(xhr.response)进行转换
1 | var url = 'http://10.10.2.111:8000/fcrepo/rest/msxAD/3202/201712214.png'; |
用表单代替ajax
通过表单的方式可以发起跨域请求,为什么 Ajax 就不会?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax 可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟是发出去了。
教程:链接
使用场景
当项目使用连连支付,请求连连的接口,报跨域错误,客户端和后端没有跨域问题,H5是有跨域问题,假如用H5请求就需要解决这一问题。这时候就需要用form表单代替ajax
使用方法
1 | function postcall( url, params, target){ |
一般跨域情况
同源策略和限制
协议、域名和端口只要有一个不同,就是跨域。意思只要3者一致,就是同源。
不同源的限制:1、Cookie、LocalStorage和IndexDB无法获取。2、无法获取和操作DOM。3、不能发送Ajax请求。
跨域通信的几种方式
1、JSONP。2、webSocket。3、CORS。4、Hash。5、postMessage
JSONP
jsonp是json with padding(填充式json或参数式json)的简写。html中script标签可以引入其他域下的js,比如引入线上的jquery库。利用这个特性,可实现跨域访问接口,需要后端支持。其中src的链接会被当成js执行。
步骤 | 操作 |
---|---|
1 | 在页面上定义数据处理函数show |
2 | 创建script标签,src的地址执行后端接口,最后加个参数callback=show |
3 | 服务端在收到请求后,解析参数,计算返回数据,输出show(data)字符串 |
4 | show(data)会放到script标签作为js执行。此时会调用show函数,将data作为参数 |
1 | //页面代码 |
webSocket
解决问题:HTTP 协议有一个缺陷:通信只能由客户端发起。webSocket的特点:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息
Hash
url的#后面的内容就是Hash,Hash改变,页面不会刷新。1
2
3
4
5
6
7
8
9
10// 举例
// A页面通过iframe嵌套了B页面,A页面给B发送消息
A页面:
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'jsonString';
B页面:
window.onhashchange = function () { //通过onhashchange方法监听,url中的 hash 是否发生变化
var data = window.location.hash;
};
CORS
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。
服务端设置Access-Control-Allow-Origin就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
当你使用Ajax发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,跟服务端的Access-Control-Allow-Origin设置进行匹配,匹配成功则在返回结果中加入一个响应头:Access-Control-Allow-Origin;
1 | //假设这个页面的域名为http://a.jrg.com |
PostMessage
window.postMessage()通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息。
window.postMessage(message, targetOrigin)发送数据,otherwindow.addEventListener(‘message’, () => {})接收数据
1、otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
2、message
要传递的数据。使用JSON.stringify()方法对对象参数序列化.
3、targetOrigin
向哪个地址发送数据1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<script>
//URL: http://a.jrg.com:8080/a.html
$('.main input').addEventListener('input',function(){
console.log(this.value);
window.frames[0].postmessage(this.value,"http://b.jrg.com:8080/b.html"); //向b.jrg.com:8080/b.html发送数据
});
</script>
<script>
// URL: http://b.jrg.com:8080/b.html
window.addEventListener('message',function(e){ //监听事件,当事件发生时接收数据
$('input') = e.data;
console.log(e.data);
});
</script>