浏览器的同源策略

模板网 2021-04-14

一、同源的三个条件

1、域名(二级域名与一级域名之间也算是不同源)
2、端口
3、协议

二、同源策略的意义

浏览器基于用户的隐私安全目的,
防止恶意网站窃取数据(只是浏览器有这个同源策略设置,但是用命令行curl请求某个跨域地址时能得到相应结果),
不允许不同域名的网站之间互相调用ajax XHR对象,
只是不允许XHR对象,对其他的图片、js脚本、css脚本还是可以通过标签跨域调用。
所以css/js/img可以跨域请求(即引用),AJAX不能请求跨域的资源。

同源策略会限制以下三种行为:
1、cookie、localStorage和indexDB无法读取
2、DOM无法获得
3、AJAX 请求无效(可以发送,但浏览器会拒绝接受响应)。

三、跨域访问的四种方式

1、JSONP实现跨域

JSONP(json with padding)方式, 通过script标签请求资源,允许用户在scr地址中传递一个callback参数(callback=abc)即将预先定义好的回调函数名以查询字符串的形式传递给服务端,服务端收到请求后会将要返回的数据用这个callback参数(abc)包裹住再返回,即将请求传入的参数abc作为函数名来包裹住要返回的JSON数据,比如abc(JSON),这样客户端在收到服务端返回的abc(JSON)文件后默认用JS解析执行。通过JSONP就可以随意定制自己的函数来自动处理返回数据了。

jsonp的原理

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中script标签引用其他域下的JS文件,比如线上jquery库,
并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。
根据这一点,可以方便地通过动态创建script节点的方法来实现完全跨域的通信。

jsonp的缺点

1、安全问题,src引用是开放的,所以jsonp的资源都被所有人访问到。
解决方法是用jsonp中的token参数,通过A域和B域共用同一套cookie来验证A的身份。
2、只能用GET方式不能用POST方式获取数据
因为是基于scr引用的,引用是get请求。
3、可被注入恶意代码如?callback=alert(1);
这问题只能用正则过滤字符串的方法解决,过滤callback后的内容不能有括号之类的条件

jsonp代码实现

1.定义数据处理函数
appendHtml(){
    xxxxx
}

2、创建script标签,src的地址执行后端接口,最后加个参数callback=appendHtml.如:
var script=document.createElement('script')
script.src="http://127.0.0.1/getNews?callback=appendHtml"

3、服务端在收到请求后,解析参数,计算返还数据,输出 appendHtml(data) 字符串。
4.前台页面收到服务端返回的appendHtml(data)字符串所构建的script标签,页面加载这个script标签时做为js执行。
此时会调用appendHtml()函数,将data做为参数。

注意:JSONP实现的前提是后端必须有JSONP的API接口,即后端有将前端传入的参数作为函数名包裹数据返回js文件的逻辑。

2、CORS 跨域资源共享 Cross-Origin Resource Sharing

CORS允许浏览器向跨域服务器发出XMLHttpRequest请求,突破了AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持,目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。CORS原理:浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。只要服务器实现了CORS接口,就可以跨源通信。

header("Accept-Control-Allow-Origin","*")//允许所有源发起的请求


如果Origin指定的源,不在服务端许可范围内,服务器会返回一个正常的HTTP回应。
但这个响应头信息没有包含Access-Control-Allow-Origin字段。
浏览器接收后就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。
这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

如果Origin指定的域名在许可范围内,服务器返回的响应,响应头会包含以下信息字段
Access-Control-Allow-Origin: http://api.bob.com
//允许来自源http://api.bob.com的访问,如果是*则代表允许来自所有源的访问

3、HTML5跨文档通信API window.postMessage

HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。 下一代浏览器都将支持这个功能。Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递。

举例,父窗口aaa.com向子窗口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(event) {
  console.log(e.data);
},false);

4、降域 实现iframe窗口跨域访问 实现不同子域页面cookies共享

当两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain来实现iframe窗口相互访问或设置cookie。降域方式只适用于同一站点下不同子域名共享cookie或者iframe页面中嵌套的子域名页面之间的访问。降域不适用访问LocalStorage 和 IndexedDB,postMessage()方法可访问LocalStorage。

举例来说,A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,子域名不同默认情况下会被同源策略阻止访问。只要将两个页面都设置相同的document.domain,两个网页就可以共享Cookie或在iframe窗口下相互访问。

document.domain = 'example.com';

服务器也可以在设置 Cookie 的时候,指定 Cookie 的所属域名为一级域名以后二级域名和三级域名不用做任何设置,都可以读取这个Cookie。比如.example.com。

Set-Cookie: key=value; domain=.example.com; path=/

https://segmentfault.com/a/1190000015764619

相关文章

  1. 使用宝塔面板定时任务不执行问题处理

    定时任务不执行 不用宝塔自带的计划任务,因为宝塔自带的计划任务无法以www:www身份去执行任务,会导致面板无法正常写入日志 在vps中输入:crontab -e -uwww ,然后贴上 * * *

  2. javascript中的正则表达式

    javascript正则表达式的定义 JavaScript中的正则表达式定义在一个RegExp对象中,通过实例化一个RegExp构造函数来创建一个正则表达式对象var pattern=new R

  3. 编程常用词汇表

    这里整理了一些常用词汇,供在编码中使用: 通用 数学 列表 时间 图像 文件目录 执行 业务 用户相关 文章相关 商品相关 优惠券相关 订单相关 这里总结了一些软件开发中常用的词汇,如

  4. redis 运维常用命令

    time #查看时间戳与微妙数 dbsize #查看当前数据库中key数量 bgrewriteaof #后台进程重写aof bgsave #后台保存rdb快照 save #保存rd

  5. Sublime Text 快捷键汇总

    [TOC] 快捷键 作用 command+q 退出sublime command+w 退出当前正在编辑的文件 command+e 使用所选内容查找 command+r 跳转定

随机推荐

  1. 使用宝塔面板定时任务不执行问题处理

    定时任务不执行 不用宝塔自带的计划任务,因为宝塔自带的计划任务无法以www:www身份去执行任务,会导致面板无法正常写入日志 在vps中输入:crontab -e -uwww ,然后贴上 * * *

  2. javascript中的正则表达式

    javascript正则表达式的定义 JavaScript中的正则表达式定义在一个RegExp对象中,通过实例化一个RegExp构造函数来创建一个正则表达式对象var pattern=new R

  3. 编程常用词汇表

    这里整理了一些常用词汇,供在编码中使用: 通用 数学 列表 时间 图像 文件目录 执行 业务 用户相关 文章相关 商品相关 优惠券相关 订单相关 这里总结了一些软件开发中常用的词汇,如

  4. redis 运维常用命令

    time #查看时间戳与微妙数 dbsize #查看当前数据库中key数量 bgrewriteaof #后台进程重写aof bgsave #后台保存rdb快照 save #保存rd

  5. Sublime Text 快捷键汇总

    [TOC] 快捷键 作用 command+q 退出sublime command+w 退出当前正在编辑的文件 command+e 使用所选内容查找 command+r 跳转定