zoukankan      html  css  js  c++  java
  • 浅谈CORS

    浅谈CORS

    CORS全称“跨站资源共享”(Cross-Origin Resource Sharing),它允许浏览器克服浏览器同源策略向跨域服务器发出请求。

    同源策略

    概念

    说到CORS,那么就不得不提浏览器同源策略,所谓“同源”,是指服务器URL的三个相同:

    1.协议相同

    2.域名相同

    3.端口相同

    举个栗子:比如一个URL是http://www.example.com:80/a.html,那么:

    http://www.example.com:80/b.html	// 同源
    https://www.example.com:80/a.html	// 非同源(协议不同)
    http://www.example1.com:80/a.html	// 非同源(域名不同)
    http://www.example.com:81/a.html	// 非同源(端口不同)
    

    限制

    如果非同源,那么三种行为将受到限制:

    1.非同源页面无法跨域读取浏览器本地数据存储(Cookie、LocalStorage和IndexDB)

    2.非同源页面无法跨域获取DOM

    3.非同源页面无法跨域发送AJAX请求

    目的

    那么,为什么浏览器要使用同源策略?

    同源策略的目的,是为了保证用户的信息安全,防止被不法分子窃取数据。而众所周知,Cookie包含大量的登录信息,如果一个网页可以跨域访问另一个网站的Cookie,那么不法分子可以通过使用跨域访问获取Cookie然后冒充用户,为所欲为。

    由此可见,同源策略是极其有必要的。

    突破同源策略

    但是,很多时候,我们需要跨域发送AJAX请求,此时我们就需要突破同源策略不允许发送跨域AJAX的规定。随着技术的发展,有很多技术可以实现跨域发送AJAX请求,常见的有以下三种:

    1.JSONP

    2.Websocket

    3.CORS

    JSONP

    JSONP是CORS技术出来之前最常用的跨域解决方案,最大的特定是兼容性好,简单,不需要进行大的服务器改动。它的基本思路是通过动态添加一个script标签,向服务器请求脚本,脚本中一般调用一个客户端定义的函数,将数据作为参数,调用客户端的函数,而客户端通过操作该函数,可以使用被当做参数传过来的数据。

    因为服务器不限制script的跨域,所以不受跨域影响。

    Websocket

    众所周知,Websocket是一个持久化协议,常用于解决服务器推送问题。但是,实际上Websocket其实支持跨域通信。通过设置Websocket的origin的字段,可以规定允许跨域的站点。

    上面两种方法虽然可以解决跨域,但是,都有着各种问题。

    庆幸的是,本文的主角:CORS的出现,彻底解决了跨域问题。

    CORS

    浏览器将跨域AJAX请求分为两类:简单请求和非简单请求,对应有两种不同的处理方式。

    简单请求

    何为简单请求?

    简单请求就是满足以下两个条件的请求:

    1.请求方法为HEAD、GET和POST

    2.HTTP请求头只包含:AcceptAccept-LanguageContent-LanguageLast-Event-ID以及值为application/x-www-form-urlencodedmultipart/form-datatext/plain三者之一的Content-Type

    对于简单请求,浏览器可以直接发送请求到服务器,但是会在请求头中添加一个origin字段,该字段用来说明请求的来源。服务器会识别该字段,判断是否允许跨域。

    如果允许跨域,服务器会返回结果并在响应头上添加三个字段:

    1.Access-Control-Allow-Origin

    该字段的值为Origin字段的值,或者是*,表示服务器接受任何源的跨域请求。

    2.Access-Control-Allow-Credentials

    可选字段,它表示是否允许发送Cookie,值为true时,表示发送请求的时候允许发送Cookie,如果不包含该字段,则表示不允许发送Cookie。

    值得一提的是,如果服务器允许发送Cookie,那么不允许将Access-Control-Allow-Origin的值设为*

    3.Access-Control-Expose-Headers

    可选字段,在没有该字段的情况下,针对跨域请求,XHR对象的getResponseHeader()方法只能拿到Cache-ControlContent-LanguageContent-TypeExpireLast-ModifiedPragma这六个字段,该字段可以设置额外可以拿到的字段。

    非简单请求

    不满足简单请求的跨域请求都是非简单请求,比如PUT或DELETE方法。

    不同于简单请求的直接向服务器请求,非简单请求会在发送之前,先进行一次“预检”(preflight),即,向服务器发出一个OPTIONS请求,查询服务器是否允许它进行跨域请求。

    如果服务器不通过“预检”,会返回一个error,客户端可以通过onerror事件进行捕获。

    当服务器通过“预检”后,服务器会进行响应,响应头中含有CORS的相关字段,分别是:

    1.Access-Control-Allow-Origin

    该字段和简单请求中的同名字段一样。

    2.Access-Control-Allow-Methods

    该字段表示服务器支持跨域的所有方法,是一个逗号分隔的字符串,如:POST,DELETE。

    3.Access-Control-Allow-Headers

    该字段表示服务器支持的所有头信息,也是一个逗号分隔的字符串。

    4.Access-Control-Allow-Credentials

    可选字段,与简单请求中的同名字段一样。

    5.Access-Control-Max-Age

    可选字段,在一段时间内,浏览器对同一个域名进行非简单跨域请求,只对第一次进行“预检”,而这一次“预检”的结果将被缓存,接下来的请求都通过该结果进行判断。该字段就是用来设置“预检”结果缓存的时间长短,可以将其值设为-1来禁用“预检”缓存。

    接收到服务器通过“预检”的响应后,客户端会正式发送真正的请求,接下来的处理方式和简单请求一致。

    总结

    在当前开发中,当不需要兼容老式浏览器中,我们一般采用CORS的方式进行跨域请求,因为相比Websocket,CORS支持非长连接场景;相比JSONP,CORS支持所有HTTP请求,用法更加平滑。

    当然,值得一提的是,当你需要兼容老式浏览器时,JSONP是你唯一的选择~

  • 相关阅读:
    lr 增强窗格中,如何生成调试信息?
    lr 自带的例子,如何进行关联,通过代码的函数进行实现
    lr11 录制脚本时候,无法自动启动ie,查了网上很多方法都未解决?
    loadrunner11 录制脚步不成功,在录制概要出现“No Events were detected”,浮动窗口总是显示“0 Events”,解决办法
    loadrunner11 安装及破解教程来自百度文库
    安装loadrunner11 ,出现如下错误如何解决?
    回收站数据删除了,如何进行恢复?
    网管工作方面——————打印机删除了然后开机重启他依然存在,如何解决
    Windows 不能在 本地计算机 启动 SQL Server 服务 错误代码126
    Sorry, the page you are looking for is currently unavailable. Please try again later. Nginx
  • 原文地址:https://www.cnblogs.com/karthuslorin/p/9615681.html
Copyright © 2011-2022 走看看