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
 

http跨域时的options请求的更多相关文章

  1. 前后端分离开发,跨域时jsessionid每次请求都变化的问题解决方法

    本解决方法的使用前提是,前端开发使用的是vue,后端使用java(SpringMVC) 在前后端分离开发过程中,可能会出现因跨域而导致每次请求的jsessionid不一致的情况 解决方法: 前端:要在 ...

  2. 当跨域时,js ajax 请求出现options请求

    上面有文章说过http的options. 查了很久.试了很多版本的jQuery,下面这段代码在同事的机子上测试是没有问题的.正常 的请求, 一在我机子上面就会出现option,网上说先向服务器预检等. ...

  3. Http跨域时的Option请求

    写这篇文章时,我们碰到的一个场景是:要给R系统做一个扩展小应用,前端的html.js放在R系统里,后端需要做一个单独的站点N.B.com.这就导致了跨域问题,而且要命的是,后端同学没有权限向招聘的系统 ...

  4. JSONP跨域的script标签请求为什么不受同源策略的限制?

    在复习跨域的时候,复习到了JSONP跨域,大家都知道JSONP跨域是通过动态创建script标签,然后通过其src属性进行跨域请求的,前端需要一个数据处理的回调函数,而服务端需要配合执行回调函数,放入 ...

  5. 跨域GET、POST请求

    跨域GET.POST请求的小结 重点:跨域POST大量数据: JQuery:$.ajax/$.getJSON支持jsonp格式的跨域,但是只支持GET方式,暂不支持POST: CORS:w3c关于跨域 ...

  6. Ajax跨域(CROS)请求中的Preflighted requests

    Ajax跨域(CROS)请求中的Preflighted requests:https://www.aliyun.com/jiaocheng/862989.html 10 分钟理解跨域请求:https: ...

  7. 跨域时发送预检请求,tp5的restful无options方法的解决方案

    解决 跨域问题解决 问题:使用vue-resource发送delete请求时报options请求404 思考:明明发送的是delete请求,为何变成了options请求? 答:跨域情况下,PUT,DE ...

  8. 彻底解决Asp.netCore WebApi 3.1 跨域时的预检查204 options重复请求的问题

    Asp.netCore WebApi 3.1 跨域的预检查options问题 1:我们直接使用core跨域的中间件 ,注入跨域服务, services.AddCors(options => { ...

  9. ajax跨域POST时执行OPTIONS请求服务端返回403forbidden的解决方法

    ajax访问服务端restful api时,由于contentType类型的原因,浏览器会先发送OPTIONS请求. 本人服务端用的是spring mvc框架,web服务器用的是tomcat的,以下给 ...

随机推荐

  1. 嵌入AppBar并且带搜索建议的搜索框(Android)

    先看结果: 相关的官方文档在这里:Creating a Search Interface Android官方提供了两种方式: 弹出一个Dialog,覆盖当前的Activity界面 在AppBar中扩展 ...

  2. 新安装的Ubuntu设置root密码

    一.问题描述 新安装的Ubuntu切换到root用户时如果没有设置root用户密码会操作失败.此时需要先设置root用户密码. 二.解决办法 打开终端执行 sudo passwd 命令. 输入设置的密 ...

  3. postman 学习网址

    postman使用详解: http://gold.xitu.io/entry/57597a62a341310061337885 https://www.getpostman.com/docs/writ ...

  4. Session in BSU CodeForces - 1027F(思维 树 基环树 离散化)

    题意: 有n门考试,每门考试都有两个时间,存在几门考试时间冲突,求考完所有的考试,所用的最后时间的最小值 解析: 对于时间冲突的考试 就是一个联通块 把每个考试看作边,两个时间看作点,那么时间冲突的考 ...

  5. 【刷题】LOJ 6003 「网络流 24 题」魔术球

    题目描述 假设有 \(n\) 根柱子,现要按下述规则在这 \(n\) 根柱子中依次放入编号为 \(1, 2, 3, 4, \cdots\) 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任 ...

  6. bzoj1018/luogu4246 堵塞的交通 (线段树)

    对于一个区间四个角的点,可以用线段树记下来它们两两的联通情况 区间[l,r]通过两个子区间[l,m],[m+1,r]来更新,相当于合并[l,m],[m+1,r],用(m,m+1)这条边来合并 查询a, ...

  7. 日志备份的shell脚本

    以前工作中写的日志备份的脚本,现记录一下日志备份脚本代码,以后工作中遇到遇到需要备份或者清理日志的时候可以拿来简单修改一下使用,减少工作量. 把备份脚本添加到Linux定时任务中,可以定时执行. 日志 ...

  8. 织梦dedecms搜索页加上序列号autoindex

    在我们做织梦搜索页模板的时候经常会使用到autoindex标签.那么怎么才能实现搜索页可以使用呢?下面给大家分享下解决方法: 打开文件:include/arc.searchview.class.php ...

  9. Angular.js浅谈

    至今博主对于MVVM框架比较了解的就只能算有Angular了,首先给大家明确一个概念,Angular1.x才能叫Angular.js,而Angular2.4.5都直接叫Angular了,因为从2开始已 ...

  10. Python基础数据类型-函数传参详解

    Python基础数据类型-函数传参详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.位置参数 #!/usr/bin/env python #_*_coding:utf-8_* ...