浏览器跨域问题

1.同源策略

同源策略是一种约定,是浏览器最核心也是最基本的安全功能。可以说Web是构建在同源策略基础之上的,浏览器之上针对同源策略的一种实现。

同源:协议,域名,端口号都相同的才称为“同源”。

同源策略用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互,能帮助阻隔恶意文档,减少可能被攻击的媒介。是浏览器行为,保护本地数据不被JavaScript代码获取回来的数据污染,拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但无法被浏览器接受。

同源策略限制的有:

1.无法读取非同源网站的Cookie、LocalStorage、IndexDB。

2.无法接触非同源网页的DOM。

3.无法想非同源地址发送AJAX请求。

2.跨域问题及解决

跨域问题

因为有同源策略的限制,会产生跨域问题,即指不同源的脚本在数据交互时,会报错。

解决途径有如下:

2.1JSONP

特点:请求方式只能是GET请求,简单。

思路:网页通过添加一个<script>元素,通过src属性向服务器发送query信息,query携带在客户端定义的函数。服务端在收到请求后,接受其函数,并在将数据作为其回调函数的参数,返回给客户端处理。

2.2CORS

跨资源共享W3C标准,需要浏览器和服务器同时支持。

在跨域中请求分为简单请求(普通HTML Form在不依赖脚本的情况下可以发出的请求)和非简单请求(需要先发起预检请求)。

为什么区分简单请求和非简单请求?

因为浏览器任务简单请求是安全的,所以可以通过跨域限制到达服务器,即无需对简单请求做预检请求。

对于非简单请求为什么要先发起一个预检请求给服务器?

跨域限制指对于请求来说,请求可以发出,但是请求响应回来的数据不被接收。但是请求已经发生,难免对服务器进行了数据操作。为避免这种情况,对于非简单请求需要首先发起预检请求,检测是否能发起真正的请求。(对于简单请求,浏览器认为其是安全的,无需发起预检请求)

预检请求的作用:询问服务器,当前网页所在的域名是否在服务器的许可名单中,以及可以使用哪些请求方法和头信息字段,获取到肯定的答复,浏览器才会发起正式的XMLHttpRequest请求,否则报错。

CORS过程

一、简单请求

浏览器直接发起CORS请求,就是在头信息中,增加一个Origin字段(说明本次请求来自哪个源)。

若指定域不在许可范围内,服务器返回一个正常的HTTP回应,不包含Access-Control-Allow-Origin字段,浏览器发现之后会抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。其错误无法通过错误码识别,因为状态码可能是200。

若指定域在许可范围内,服务器返回的HTTP回应含以下头信息字段:

Access-Control-Allow-Origin:xxx 当字段值为*时,表示接受任何域名的请求。

Access-Control-Allow-Credentials:true/false 可选值,表示是否允许发送cookie。(默认情况下,cookie不包含在CORS请求中)为true,表示服务器允许cookie包含在CORS请求中。若服务器不需要cookie,删除该字段即可。

Access-Control-Expose-Headers:xxx 可选值,表示可以用getResponseHeader(‘字段名’)方法获取到的头信息字段。原XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段。

!注意:当CORS请求要携带cookie发送到服务器时,一方面需要服务器同意(Access-Control-Allow-Credentials:true);另一方面开发者需要在AJAX请求中设置withCredentials属性(xhr.withCredentials = true)否则就算服务器允许发送cookie,浏览器也不会处理。有些时候虽未设置withCredentials,但有些浏览器还是会一起发送cookie,这是可以设置withCredentials属性为false,显式关闭。

要发cookie,Access-Control-Allow-Origin不能设置为*,需指定明确的与请求网页一样的域名。

二、非简单请求

对服务器有特殊要求的请求,如请求方法是PUT/DELETE,或是Content-Type字段类型是application/json。

在正式请求前,会增加一次“预检”请求。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单中,以及可以使用哪些请求方法和头信息字段。确定之后,当判断正确,才会根据返回的信息发送请求。

预检请求的请求方法是OPTIONS,会携带以下字段:

1.Origin:请求来自哪个域。

2.Access-Control-Request-Method:列出浏览器CORS请求会用到哪些HTTP请求。

3.Access-Control-Request-Headers:列出浏览器CORS请求会额外发送的头信息字段,有多个时,用逗号隔开。

服务器收到预检请求后,检查上诉上个字段,确认允许跨域请求,作出回应

若服务器否定了预检请求,会返回一个正常的HTTP响应(无任何与CORS相关的头信息字段),浏览器识别服务器不同意请求时,错误会被XMLHttpRequest的onerror回调函数捕获。

若服务器通过预检请求,会返回一个HTTP响应,包含如下字段:

1.Access-Control-Allow-Origin:允许的域

2.Access-Control-Request-Methods:返回服务器允许的所有请求方法,多个用逗号隔开

3.Access-Control-Request-Headers:返回服务器允许携带的所有头信息字段,多个用逗号隔开

4.Access-Control-Allow-Credentials:是否允许请求中携带cookie

5.Access-Control-Max-Age:可选值 表示本次预检的有效期 单位为秒 在此期间,无需重新发送方预检请求进行预检

整个CORS通信过程,都是浏览器自动完成,无需用户参与,浏览器一旦发现AJAX请求请求跨域,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨域通信

CORS允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制

CORS跨域的特点:服务器代码需要添加一段解决跨域的代码,确保在特定源下的网页可以接受服务器请求的响应数据。

response.setHeader("Access-Control-Allow-Origin","*")

3.添加跨域访问的中间件

如gin框架,有开源的跨域访问中间件

在Express中,可以使用cors模块实现跨域访问

4.postMessage

HTML5引入的api,postMessage()允许来自不同源的脚本采用异步方式进行有效的通信,多用于窗口间数据通信。

eg.页面b通过iframe标签放入页面a,通过postMessage和onmessage实现相互通信

5.window.name

有三个html页面,a页面和b页面同域,c页面独立。第一步,a页面的iframe标签的src属性指向c页面地址。第二步,在a页面的iframe标签上定义一个onload方法,其作用是将src地址改为b页面地址。当a页面请求c页面时,c页面抛出一个window.name,这个方法在a页面访问b页面的时候仍然存在。

6.Hash

同window.name一样,a页面和b页面同域,c页面独立。a页面通过iframe标签的src属性带一个hash值传递给c页面,c页面获取其hash值,创建一个iframe标签,通过src将修改后的hash传给b页面,a页面可以通过监听b页面的hash变化获取c页面的hash值。

7.document.domain

利用document.domain指定域,但是需要一级域名一致才可以使用。

当需要在“www.sojson.com/shiro”中上传图片到“cdn.sojson.com/images/”中,需要在请求两个页面时,都加上document.domain = “sojson.com”。

8.WebScoket

WebSocket是HTML5中提出的持久化协议,是一种网络传输协议,位于OSI模型的应用层,可以在单个TCP连接上进行全双工通信,能够更好的节省服务器资源和带宽,并达到实时通讯

服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送消息,属于服务器推送技术的一种。

基于HTTP1.1协议完成1次握手,创建WebSocket连接。

在WebSocket之前,开发实时web应用的方式是轮询

轮询:在特定的时间间隔不断向服务器发送HTTP请求,问有无数据,有数据的话服务器就用响应报文回应,当轮询的频率比较高时,就可以近似实现“实时通信”的效果。

轮询的缺点:HTTP请求可能包含较长的头部,真正有效额数据只是很小的部分,会浪费很多带宽资源。

WebSocket协议的特点:

1.全双工。通信允许数据在两个方向上同时传输。自身就是全双工,不需要服务器推送。

2.二进制帧。采用二进制帧结构,语法和语义与HTTP协议完全不兼容,更侧重于“实时通信”。(HTTP协议更侧重传输效率)更好的处理二进制内容。

3.协议名。引入ws和wss代表明文和密文的WebSocket协议,默认端口使用80或443,几乎和HTTP协议一致。

4.较少的控制开销。数据包头部协议较小,不同于HTTP每次请求都需要携带完整的头部。

5.保持连接状态。创建连接后,成为一种由状态的协议,可以省略状态信息,不同于HTTP每次请求需要携带身份验证信息。

9.nginx后端配置

10.proxy反向代理

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值