zoukankan      html  css  js  c++  java
  • http跨域时的options请求

    1、背景

      在前后端分离的项目中经常会遇到跨域请求的问题,如果没有进行跨域配置,会浏览器请求失败。我一般采用两种解决方案:

      1、采用nginx进行转发,是前后端服务处于同一个域下面,从根本上避免跨域问题。

      2、后端服务做一些配置,允许请求跨域,从而解决浏览器跨域问题。但是有时候浏览器还会发送OPTIONS请求。

    2、跨域请求

      跨域请求的介绍,以及处理方式可以看https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS,说的非常详细

      简单说就是,浏览器地址栏中的的域和即将加载的请求的域不是同一个,比如域名或端口不同,浏览器就会把这个当成跨域请求,如果服务端没有正确的返回对应的响应头,那么请求就会被拦截。导致请求失败。

    3、两种跨域请求方式

      浏览器将CORS请求分为两类:简单请求(simple request)和需要预检的请求(Preflighted requests),这两种方式有什么区别?

      简单请求不会发送CORS preflight,也就是正式请求前不会发送OPTIONS请求,而是添加必要的请求头后直接发送请求。必须同时满足以下几个要求才能称之为简单请求:

      不满足上面条件的跨域请求都称为需要预检的请求,请求前都会先发送OPTIONS请求。

      如下面得列子,这个跨域请求就是简单请求,满足上面提到得几个条件。

      由于是跨域请求,浏览器追加了Origin头,表示当前浏览器地址上面的域是http://foo.example。响应中多了Access-Control-Allow-Origin头,表示允许访问的域,*表示允许所有的域访问。如果服务端没有这个返回这个响应头,或者响应头中值不包含Origin中的域,浏览器就放弃这个响应。

    GET /resources/public-data/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Connection: keep-alive
    Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
    Origin: http://foo.example
    
    
    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 00:23:53 GMT
    Server: Apache/2.0.61 
    Access-Control-Allow-Origin: *
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Transfer-Encoding: chunked
    Content-Type: application/xml

    4、预检的请求(Preflighted requests)

      不是简单请求,浏览器在跨域请求前都会发送预检,主要是把即将要进行的跨域请求的信息发送给服务端,看服务端受否支持,如果支持,则发送对应的响应头,这时才正式发送跨域请求。

      例如下面的预检请求,除了发送Origin头外,还发送了Access-Control-Request-Method和Access-Control-Request-Headers,用来告诉服务端,接下来的跨域请求是post,携带了简单请求外的一些头X-PINGOTHER和Content-Type。如果服务端允许此次跨域请求,那么就需要合理的响应OPTIONS请求,如:

      Access-Control-Allow-Origin: http://foo.example    允许http://foo.example的域的请求
      Access-Control-Allow-Methods: POST, GET, OPTIONS   支持跨域的方法有这三个
      Access-Control-Allow-Headers: X-PINGOTHER, Content-Type    支持跨域的头有
      Access-Control-Max-Age: 86400

      浏览器收到响应后,如果响应满足那么则正式发送跨域请求。

    OPTIONS /resources/post-here/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Connection: keep-alive
    Origin: http://foo.example
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: X-PINGOTHER, Content-Type
    
    
    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:15:39 GMT
    Server: Apache/2.0.61 (Unix)
    Access-Control-Allow-Origin: http://foo.example
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    Access-Control-Max-Age: 86400
    Vary: Accept-Encoding, Origin
    Content-Encoding: gzip
    Content-Length: 0
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Content-Type: text/plain

      接着看预检请求之后的请求,和简单请求一致,请求头多了Origin,响应头多了Access-Control-Allow-Origin。从这可以看出,非简单请求会发送预检请求,之后再发送正式请求,正式请求和简单请求的跨域头一致。

    
    POST /resources/post-here/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Connection: keep-alive
    X-PINGOTHER: pingpong
    Content-Type: text/xml; charset=UTF-8
    Referer: http://foo.example/examples/preflightInvocation.html
    Content-Length: 55
    Origin: http://foo.example
    Pragma: no-cache
    Cache-Control: no-cache
    
    <?xml version="1.0"?><person><name>Arun</name></person>
    
    
    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:15:40 GMT
    Server: Apache/2.0.61 (Unix)
    Access-Control-Allow-Origin: http://foo.example
    Vary: Accept-Encoding, Origin
    Content-Encoding: gzip
    Content-Length: 235
    Keep-Alive: timeout=2, max=99
    Connection: Keep-Alive
    Content-Type: text/plain
     
  • 相关阅读:
    从零开始学SQLSERVER-UNION
    从零开始学SQLSERVER-BETWEEN
    从零开始学SQLSERVER-LIKE
    从零开始学SQLSERVER-存储过程(基础用法)
    从零开始学SQLSERVER-TOP
    从零开始学SQLSERER-INNER JOIN
    从零开始学SQLSERVER-DELECT(删除)
    从零开始学SQLSERVER-ORDER BY(排序)
    从零开始学SQLSERVER-WHERE
    使用 C# 9 的records作为强类型ID
  • 原文地址:https://www.cnblogs.com/lilinwei340/p/10177132.html
Copyright © 2011-2022 走看看