跨域问题

[TOC]

1. 简介

  1. CORS全称 Cross-Origin Resource Sharing,跨源资源共享,是跨域的解决方案之一.

  2. 浏览器的同源策略是一个重要的安全机制,不同源的客户端在没有授权的情况下,不能够访问对方的资源。

  3. 同源的定义是访问链接的协议、域名和端口号均相同。在实际应用中,合理的跨域请求对于一些应用程序也很重要,

  4. CORS 标准定义了在访问跨域资源时,浏览器与服务器应该如何沟通。CORS 的基本思想是使用 HTTP 头部让浏览器与服务器进行沟通,从而决定请求是否能够成功。需要服务器支持。

  5. 在 CORS 成为标准之前,由于安全原因,没有办法跨域调用 API。也就是(一定程度上依旧是)被所谓同源策略(Same-Origin Policy)限制住了。同源策略是浏览器限制的。

2. 同源策略

1. 介绍

  1. 基于CSRF等安全隐患,浏览器会限制从脚本发出的跨域请求,虽然安全性更高,页面体验却差了。于是W3C推出了一种跨域的访问验证的机制,即CORS,这种机制支持跨域请求,且跨站数据传输更安全。

  2. CORS验证机制需要客户端和服务的协同处理。

2. 为什么要有同源策略

  1. 防止CSRF攻击

3. CSRF是什么

  1. CSRF叫做跨站请求伪造攻击Cross-site request forgery,也有叫XSRF的。是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨網站指令碼(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

  2. 简单点说,CSRF 就是利用用户的登录态发起恶意请求。

  3. 比如用户给服务器发送一个GET请求,获得个人数据,之前用户已经登录过了,浏览器保存有Cookie。现在有个第三方网站,弄一个图片链接,实际链接内容是这个GET请求,如果用户点了后,利用本地保存的Cookie,就返回了这个用户的个人数据。

  4. 这个第三方网站和服务器不同源(ip、端口、域名),为了防止CSRF,同源策略是个解决办法,比如,如果用户要删除自己的帖子,那么先要登录 www.c.com,然后找到对应的页面,发起删除帖子的请求。此时,Referer 的值是 http://www.c.com;当请求是从 www.a.com 发起时,Referer 的值是 http://www.a.com 了。因此,要防御 CSRF 攻击,只需要对于每一个删帖请求验证其 Referer 值,如果是以 www.c.com 开头的域名,则说明该请求是来自网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是 CSRF 攻击,可以拒绝该请求。

  5. 但是有些它就是要不同源访问,于是就有了CORS验证机制。

4. XSS是什么

  1. xss本质是html注入,和sql注入差不多.

  2. 比如注册用户时,用户输入"张三"并提交,服务端会生成:

    欢迎新用户,张三

    。如果用户输入:alert('逗你玩'),服务端就会生成:

    欢迎新用户,alert('逗你玩')

    。输入用户内容就会被浏览器识别为指令执行,这就是xss注入。

3. CORS验证机制

1. 客户端处理机制

  1. 浏览器会对所有跨域请求进行验证,分为简单请求验证处理和预检请求验证处理。那么对应的就有简单请求和非简单请求之分。

1. 简单请求

  1. 若一个请求同时满足以下两个条件,那么则为简单请求。

    • 请求方法为GET或HEAD或POST

    • 请求头中的Content-Type值为application/x-www-form-urlencoded 或 multipart/form-data 或 text/plain

  2. 对于简单请求,浏览器直接发送该请求,在同一个请求中作跨域验证。怎么验证呢?在请求头上附上Origin属性,表明这是一个跨域请求。服务器接到请求,根据设定的跨域规则来验证,验证通过,返回Access-Control-Allow-Origin等以Access-Control-开头的响应头以及请求的资源,否则返回403状态码,且不会返回请求的资源。

2. 非简单请求

  1. 不为简单请求的跨域请求均为非简单请求。非简单请求的跨域验证通过一个预检请求来验证,即在发送一个正式的跨域请求之前,发送一个预检请求,用来检查当前网页所在的域名是否在服务器的许可名单中以及可使用哪些请求方法,请求头字段。

  2. 预检请求

    • 请求方法为OPTIONS

    • 请求头字段包括 Origin, Access-Control-Request-Method(表明正式的跨域请求可能用到的方法),Access-Control-Request-Headers(表明正式的跨域请求可能用到的头字段)

  3. 预检请求通过,发送正式的跨域请求,请求头带Origin字段。

  4. 携带证书信息的请求

    • 一般情况下,跨域请求不携带证书信息。但若请求的证书模式(credentials mode)被设为include,那么表明该请求需要携带证书信息。

    • 在简单请求及正式的非简单请求中,请求头附带证书信息,响应头回应:Access-Control-Allow-Credentials:true,并返回请求资源。

    • 在预检请求中,请求头并不会附带证书,响应头会回应:Access-Control-Allow-Credentials:true。

    • 若服务器端同意请求携带信息,则Access-Control-Allow-Origin不能为*,只能为请求头中指定的Origin值。

2. 服务端处理机制

  1. 检查http头部是否有Origin字段

  2. 没有或不允许,则当作普通请求处理,结束

  3. 若有且允许跨源,再看是否是预检请求(method为OPTIONS)

  4. 是预检请求,返回Access-Control-Allow-Origin,Access-Control-Allow-Methods等信息,内容为空

  5. 不是预检请求,返回Access-Control-Allow-Origin,Access-Control-Allow-Credentials等信息,内容为请求的资源。

4. CORS 规则

1. option

  1. CORS 标准中新增了一组 HTTP 首部字段,用于浏览器和服务器之间沟通。在跨域请求中,在一些情况下会有一个预检请求(preflight request),是用来检查是否允许这种类型的请求,这种请求使用 OPTIONS 方法。预检请求的使用,可以避免跨域请求对服务器的数据产生未预期的影响。

  2. 什么情况下回触发预检请求?

    1. 使用 PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH 中任一方法。

    2. 人为设置了对 CORS 安全的首部字段集合之外的首部字段,该集合在正式标准中包含 Accept、Accept-Language、Content-Language、Content-Type(还有额外限制)。

    3. Content-Type 的值不是 application/x-www-form-urlencoded、multipart/form-data、text/plain 其中之一。

    4. 请求中 XMLHttpRequestUpload 对象注册了事件监听器。

    5. 请求中使用了 ReadableStream 对象。

  3. 不会触发预检请求的情况?

    1. 使用 GET、HEAD、POST 方法之一。

    2. 不得人为设置对 CORS 安全的首部字段集合之外的首部字段,该集合在正式标准中包含 Accept、Accept-Language、Content-Language、Content-Type(还有额外限制)。

    3. Content-Type 的值仅限 application/x-www-form-urlencoded、multipart/form-data、text/plain 其中之一。

    4. 请求中 XMLHttpRequestUpload 对象没有注册任何事件监听器。

    5. 请求中没有使用了 ReadableStream 对象。

2. 请求头

  1. Origin

    • 表示跨域请求或预请求来自哪里。

  2. Access-Control-Request-Method

    • 在使用 OPTION 方法时会用到,表示对同一资源的将来跨域请求可能使用的方法。

  3. Access-Control-Request-Headers

    • 在使用 OPTION 方法时会用到,表示对统一资源将来跨域请求可能使用的请求头部。

3. 响应头

  1. Access-Control-Allow-Origin

    • 表示是否能够共享响应。如果服务器认为请求可以接受,就设置该头部为请求头的 Origin 信息或者 * ;如果没有这个头部,或者这个头部的信息跟请求的 Origin 信息不匹配,浏览器就会驳回请求。

  2. Access-Control-Allow-Credentials

    • 表示跨域请求是否提供凭据。默认情况下,跨域请求不提供凭据,设置该头部为 true 时,表示对应的请求应该发送凭据。如果服务器的响应中没有设置该头部,但发送的请求中带了凭据,浏览器会调用到 onerror 事件处理程序。如果是 fetch 请求,该值设置为 include 。

  3. Access-Control-Allow-Methods

    • 表示跨域请求支持的方法。

  4. Access-Control-Allow-Headers

    • 表示跨域请求支持的头部。

  5. Access-Control-Max-Age

    • 表示预请求可以缓存多长时间,以秒为单位。

  6. Access-Control-Expose-Headers

    • 通过列出其名称,指示哪些头部可以作为响应的一部分公开。

最后更新于

这有帮助吗?