zoukankan      html  css  js  c++  java
  • 跨域-转>预解析OPTIONS请求

    https://www.jianshu.com/p/b55086cbd9af

    补充下options请求:

     HTTP的options方法用于获取目的的资源所支持的通信选项。客户端可以对特定的URL使用OPTIONS方法,也可以对整站(通过将URL设置为*)使用该方法。

    三大特点:

    1.标准 OPTIONS 不发送请求体,不会附带请求数据;

    2.成功的返回没有响应体,响应体(Response body)为空。

    3.OPTIONS 是一种安全的请求,不会修改服务器资源。

    两种用途:

    1.检测服务器所支持的请求方法

    2.CORS 中的预检请求

    几个问题?

    1.预检请求有什么作用?

    CORS 中的预检请求

    在 CORS 机制中,客户端将请求分为了两种:简单请求非简单请求当请求为非简单请求时,就会触发浏览器发送预检请求,这是浏览器的行为。

    预检请求会向服务器确认跨域是否允许,服务返回的响应头里有对应字段Access-Control-Allow-Origin来给浏览器判断:如果允许,浏览器紧接着发送实际请求;不允许,报错并禁止客户端脚本读取响应相关的任何东西。

    所以,一个 POST 请求并且请求头添加了Content-Type: application/json ,浏览器判定为非简单请求,自己先发一个 OPTIONS 给服务器获取做跨域判定,获取响应后浏览器发现可以跨域,接着就发送真实的 POST。

    这里就解答两个问题了,接下来就是为什么预检请求选择了 OPTIONS 呢?

    来看预检请求的流程,如果是一个跨域请求,浏览器会自动给该请求带上 Origin 头部,标明当前请求的来源域;服务器判断这个请求是否允许跨域,就会在返回时,选择是否带上 Access-Control-Allow-Origin 头部,最后,浏览器判断 Access-Control-Allow-Origin 就知道,后续请求是否发送。

    这个流程中,对预检请求方法的要求:

    1. 不需要带请求体,服务器判断的依据在 Request header 中;
    2. 服务器返回不需要响应体,浏览器判断的依据在 Response header 中;
    3. 请求不会去修改服务器资源,要是一个安全的请求;
    4. 浏览器默认不会缓存,需要每次发送跨域验证;

    但是,这里还是有问题:

    1. 既然服务端做了请求限制,而且浏览器判断跨域只和 Access-Control-Allow-Origin 有关,预检请求是否有点多余?
    2. 原生 form 表单可以提交 POST 请求,而且为一个简单请求,很可能修改服务端数据,仅仅依靠 CORS 机制也不安全。(需要在跨域基础上的简单请求,这个简单请求是表单请求,他虽然跨域了,但是不会触发options请求,就还会对服务器的数据可能发生了改动),所以接下来就是要说:

    预检请求的意义

    浏览器为了安全的数据传输,提出了 CORS 机制,它更像一种授权机制,需要浏览器和服务器共同配合实现,对于没有实现此机制的客户端,比如 curl,是不受限制的:()

     

     上图中,服务器实现很简单,仅仅返回预先定义好的数据,curl 的返回头中也没有和Access-Control-*相关字段,但是返回体中,我们能够看到返回数据,想必解析出来也并不困难。同样的请求在浏览器中就会报错了:

     在cors机制中,服务器肯定有一套专门处理禁止跨域的逻辑,(虽然跨域是浏览器的自我保护行为,但是只是发出去了,浏览器把响应拦截了,既然能发出去,就可能会对服务器数据造成修改,这对服务器来说是不安全的),这些逻辑可能是复杂和高消耗的。如果客户端发送的请求,服务器都要经过一个复杂的逻辑才能知道是否跨域了,服务器的压力和用户体验都不好,所以这时候预检测就应运而生,发送请求前,先发送预检请求询问服务器是否允许跨域,不允许就不发送实际请求,服务器只需要对预检请求进行跨域处理。

    这样来看,在 CORS 机制中,发送预检请求是一种保护机制,保护资源不被未授权的请求修改。

    和授权服务很像,预检请求通过了,浏览器后续对同一服务的请求,不需要做跨域询问,如果服务端不想支持跨域访问,啥也不用做。

    但是重点来了:

    form表单为什么即使跨域了也不会触发浏览器的跨域提示 ?

    跨域本质是浏览器对响应数据的一种拦截,自我保护,而form表单呢是只提交,不求回报。没有返回数据,自然就不会被浏览器拦截掉,也就不会报跨域错误。ajax提交是需要返回的,也正是因为这个,才有了CSRF跨站攻击。人家直接注入。

    form表单为什么不会触发options请求?

    对于传统表单请求,都是简单请求(因为form表单只支持get和post)

    如enctype =“multipart/form-data”,提交了是一个外域地址,虽然跨域了,但是不会触发触发options检测,因为只有复杂请求才会。也不会提示跨域(源生form表单请求就算跨域也不会触发浏览器的跨域拦截),因为他只提交,不返回。他还是可能会对服务端数据造成修改。所以服务端需要做请求来源限制。意思就是需要后端对来源做限制,如设置白名单。单纯的依靠浏览器自发的OPTIONS也不可靠。因为他不管form表单提交。

  • 相关阅读:
    开源项目
    [Accessibility] Missing contentDescription attribute on image [可取行]失踪contentDescription属性图像
    Android 布局 中实现适应屏幕大小及组件滚动
    EF 错误记录
    EasyUI 加载时需要显示和隐藏 panel(面板)内容破版问题
    IE 报表缩放后页面破版
    VS 2017 引入nuget 问题
    SSRS 报表显示页面 asp net session丢失或者找不到 asp net session has expired or could not be found()
    log4net 配置
    网站
  • 原文地址:https://www.cnblogs.com/haoqiyouyu/p/14407476.html
Copyright © 2011-2022 走看看