AJax技术

再也不学AJAX了(三):跨域获取资源②JSONP CORS(2)

字号+ 作者:H5之家 来源:H5之家 2017-12-13 12:36 我要评论( )

最后,我们还要对JSONP技术再强调两点: JSONP技术与AJAX技术无关:虽然同样牵扯到跨域获取资源这个主题,但我们应该已经清楚的看到,JSONP的本质是绕过AJAX获取资源的机制,使用原始的 src 属性获取异域资源; JSO

最后,我们还要对JSONP技术再强调两点:

  • JSONP技术与AJAX技术无关:虽然同样牵扯到跨域获取资源这个主题,但我们应该已经清楚的看到,JSONP的本质是绕过AJAX获取资源的机制,使用原始的 src 属性获取异域资源;
  • JSONP技术存在一下三点缺陷:
  • 无法发送POST请求,也就是说JSONP技术只能用于请求异域资源,无法上传数据或修改异域数据;
  • 无法监测JSONP请求是否失败;
  • 可能存在安全隐患:别忘了,JSONP之所以能成功获取异域服务器资源,靠的是服务器动态生成了回调函数,并在页面中执行,那么如果服务器在原有的回调函数下再添加些别的恶意JavaScript代码会怎样?当然也会被执行!所以在使用JSONP技术时,一定要确保请求资源的服务器是值得信赖的;
  • 虽然存在一些缺陷,但JSONP的浏览器兼容性却是非常好的,可以说是一种非常小巧高效的跨域资源获取技术。

    (二)官方推荐的跨域资源共享方案:CORS

    CORS是W3C颁布的一个浏览器技术规范,其全称为“跨域资源共享”(Cross-origin resource sharing),它的意义在于,它是由W3C官方推广的允许通过AJAX技术跨域获取资源的规范,因此相较于JSONP而言,功能更加强大,使用起来也没有了hack的味道。

    关于CORS的具体细节,我建议你可以移步阮一峰的同主题博客阅读,我认为该文章已经将这个主题讲解的十分透彻了。

    你当然也可以选择继续向下阅读,看看我是怎样理解CORS技术并重新梳理CORS技术相关知识的,希望也能给你带来帮助。

    我们之前提到过,如果想要绕过浏览器“同源策略”,实现使用AJAX技术跨域获取资源,需要服务端和客户端的协同合作。而对于CORS标准而言,实现AJAX跨域获取资源,重点还在于服务器端返回的响应是否清楚的告知了浏览器此次跨域AJAX请求的合法性。

    那么?服务器端该如何向浏览器传达这一信息呢?答案是要看AJAX请求的复杂程度,也就是说,对于简单的AJAX请求,服务器要向浏览器做出的“说明”就少,而如果是复杂的AJAX,服务器则要向浏览器多“解释”几句。

    那么,如何区分AJAX请求的复杂度呢,标准在于简单的AJAX请求 只符合 下面两个条件:

  • 请求方法只属于 HEAD , GET , POST 请求的其中一种;
  • HTTP的头信息只限于以下字段:
  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type(只能为 application/x-www-form-urlencoded , multipart/form-data 和 text/plain 其中一种)
  • 而当浏览器检测到一个简单的跨域AJAX请求,浏览器会首先为我们添加一个头部信息: Origin 它的值为请求发送代码所在的源(希望你还记得,一个 源 由“ 协议 ”,“ 域名 和 端口 ”组成)。类似这样:

    GET /cors HTTP/1.1 Origin: Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0 ...

    而当这样的一条HTTP请求发送到服务端时,服务端会检测该请求报头中的 Origin 字段的值是否在许可范围内,如果的确是服务端认可的域,那么服务端会在响应报文中添加如下字段:

  • Access-Control-Allow-Origin (必须):该字段用来告知浏览器服务端接受的能够发送跨域AJAX请求的域,它的值要么是该次AJAX请求报头中由浏览器自动添加的 Origin 值,要么还可以是一个 * 号,表示可以接受任意的域名请求;
  • Access-Control-Allow-Credentials (可选):该字段用来告知浏览器是否允许客户端向服务端发送Cookie。默认情况下,CORS规范会阻止跨域AJAX向服务端发送Cookie,因此该字段默认值为 false ,当你显式的将该字段值设置为 true 时,则表示允许此次跨域AJAX向服务端发送Cookie。
  • Access-Control-Expose-Headers (可选):该字段用来向客户端暴露可获取的响应头;
  • CORS规范规定,客户端 XMLHttpRequest 对象的 getResponseHeader() 方法只能拿到6个基本的字段: * Cache-Control :表示响应遵循的缓存机制; * Content-Language :表示响应体的语言; * Content-Type :表示响应体的MIME类型; * Expires :表示文档的过期时间,到期不再缓存; * Last-Modified :表示文档的最后改动时间; * Pragma :用来包含特定的指令; 但是当客户端想要获取额外的响应头字段时,就需要服务端通过在该字段后定义相应的客户端可获取的响应头字段名称。

    以上就是简单跨域AJAX请求,客户端与服务端的交互,在继续介绍复杂的跨域AJAX请求前,让我们先停一停,回过头来看看响应报头的 Access-Control-Allow-Origin 字段,谈一谈CORS规范中为什么默认不允许跨域AJAX请求携带Cookie,以及如果客户端需要传送Cookie时,客户端与服务端又该如何交互的问题。

    首先,我们要知道,在客户端与服务端数据传输的过程中,Cookie一直是以明文的形式伴随着数据的传输,只要客户端发送了Cookie至服务端,服务端就会至少返回该段Cookie。而我们又提到过,大多数网站都使用Cookie短暂存储用户会话中的身份信息,因此将Cookie暴露在外是存在安全隐患的,CSRF攻击的目的便是获取用户的Cookie信息,因此在跨域AJAX请求中,为了减少Cookie泄露的风险,CORS规范默认禁止跨域AJAX请求携带Cookie。

    那么如果客户端实在需要携带Cookie信息怎么办呢?正如上文提到过的,需要客户端与服务端一起配合,让我们看看具体细节:

  • 首先是客户端:
  • 开发者需要在创建XMLHttpRequest对象实例时,手动配置 withCredentials 属性,将其值设置为 true :

    var xhr = new XMLHttpRequest() xhr.withCredentials = true

    某些浏览器会默认允许在跨域AJAX请求中发送Cookie,此时如果不想要发送Cookie,你只需要将其值设置为 false 。

  • 其次是服务端:
  • 对于服务端而言,除了像之前提到的要在响应报头设置 Access-Control-Allow-Credential 字段的值为 true 之外,还需要为 Access-Control-Allow-Origin 字段设置一个明确的域,不可以再使用 * 号。

    相信你也能明白,这一切都是为了保护客户端与服务端Cookie的隐私和安全。

    现在我们可以继续我们的主题,一起看一看如果我们的跨域AJAX请求超出了“简单”的标准,客户端与服务端又应该如何相互配合,实现跨域的资源共享。

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 通过Ajax方式上传文件,使用FormData进行Ajax请求

      通过Ajax方式上传文件,使用FormData进行Ajax请求

      2017-12-13 14:55

    • PHP ajax 分页类代码

      PHP ajax 分页类代码

      2017-12-12 18:14

    • Access-Control-Allow-Origin与Ajax跨域解决方法

      Access-Control-Allow-Origin与Ajax跨域解决方法

      2017-12-12 18:00

    • 从零开始学习jQuery (六) AJAX快餐(10)

      从零开始学习jQuery (六) AJAX快餐(10)

      2017-12-12 09:22

    网友点评
    n