浅谈浏览器同源策略和跨域解决方案

1. 同源策略

1.1 定义

所谓同源是浏览器的一种安全策略:若两个地址的域名协议端口 相同,则它们是同源的。

域名:网站ip的唯一标识,如www.baidu.com,www.qq.com

协议:浏览器连接并访问资源的遵从的统一约定。主要为http和https两种。

端口:不同的端口对应不同的应用程序,http网站首页一般默认端口为80端口,https则为443。

示例(以http://www.example.com/list.html为对比地址):

URL是否同源
http://test.example.com/list.html否,域名不同
https://www.example.com/list.html否,协议不同
http://www.example.com:8080/list.html否,端口不同
http://www.example.com/detail.html

1.2 产生原因和影响

同源策略存在于浏览器端是一种约定,用来保护浏览器的数据安全和用户的隐私安全。如果没有同源策略,A网站可以随意访问B网站的Cookie等信息是不安全的,现在所有支持JavaScript 的浏览器都会使用这个策略。

2. 跨域

2.1 跨域限制

不同源的地址之间无法通过ajax,fetch等途径进行访问。这种请求称之为跨域请求。但是对于图片、js脚本、css资源这种静态资源文件还是可以通过对应的img标签,script标签和link标签跨域进行调用。

此外,浏览器的Cookie、WebStorage 和 IndexedDB数据也无法跨域读取。

2.2 跨域解决方案

2.1.1 CORS跨域资源共享(主流方案)

CORS(Cross-origin resource sharing,跨域资源共享)是一个 W3C 标准,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通**(需要客户端和服务端协同处理)**。

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

浏览器将跨域请求分为两类,浏览器对这两种请求的处理,是不一样的

1:简单请求(同时符合下面两种情况)

请求方法是下列之一:

  • GET
  • HEAD
  • POST

HTTP请求头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

简单请求时,浏览器会直接发送跨域请求,并在请求头中携带Origin并赋值为当前域名,表明这是一个跨域的请求。

服务器端接到请求后,会根据自己的跨域规则,通过Access-Control-Allow-Origin(允许的跨域请求域名)和Access-Control-Allow-Methods(允许的跨域请求方式)响应头,来返回验证结果。如果验证成功,则会直接返回访问的资源内容。

简单请求

如果请求时Origin指定的源,不在服务端设置的对应响应头的许可范围内,一般服务器会返回一个403 Forbidden的HTTP响应和控制台错误。

403

2:非简单请求(不属于简单请求的跨域请求)

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。浏览器发出的Preflighted requests是一个OPTION请求

OPTIONS请求头部中会包含以下头部:

  • Origin:表示请求来自哪个源。
  • Access-Control-Request-Method必填,用来列出浏览器的CORS请求会用到哪些HTTP方法。
  • Access-Control-Request-Headers:该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

服务器收到"预检(OPTIONS)"请求以后,检查了OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段以后,设置比如Access-Control-Allow-MethodAccess-Control-Allow-Headers头部与浏览器沟通来判断是否允许这个请求。

非简单请求1

如果Preflighted requests验证通过,浏览器才会发送真正的跨域请求。

非简单请求2

如果Preflighted requests验证失败,则会返回403状态,浏览器不会发送真正的跨域请求。

2.1.2 JSONP

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

示例:

JSONP

原理:

页面虽然不允许发起跨域的ajax请求,但引用不同域名的js脚本是可行的。

  1. 执行跨域的ajax请求时会自动发起一个Script请求,请求文件名为callback=jQueryxxx,jQueryxxx是jquery随机生成的一个回调函数名称。
  2. 该次请求返回来的结果则是jQueryxxx()函数调用字符串,执行这个函数完成跨域请求。

一句话来概括就是,通过动态创建script标签,然后利用 src 属性进行跨域,而每一次跨域就是一个script脚本的引入。

缺点:

1.安全问题,src引用是开放的,所以jsonp的资源都被所有人访问到。解决方法是用jsonp中的token参数,通过A域和B域共用同一套cookie来验证A的身份。

2.只能用GET方式不能用POST方式获取数据即只能读不能写。

3.可被注入恶意代码如?callback=alert(1); 这问题只能用正则过滤字符串的方法解决,过滤callback后的内容不能有括号之类的条件。

2.3 withCredentials 属性

默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。

使用方法:

  • 客户端必须在AJAX请求中打开withCredentials属性
  • 服务器端设置响应头Access-Control-Allow-Credentials: true
  • 服务器端设置响应头Access-Control-Allow-Origin的值来指定允许跨域的域名且必须为一个确定域名,而不能使用*这样的通配符。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值