问题背景
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域
在前后端开发过程经常会遇到跨域问题。网上也都有解决方案。


写这篇文章时,我们碰到的一个场景是:要给s系统做一个扩展,前端的html、js放在s系统里,后端需要做一个单独的站点N.B.com。这就导致了跨域问题,大多数时候 前后端用一个CORS方案 解决跨域问题就可以了。但是我这次有点特别。


前端这边是一个get请求,按理说也没啥,但是在请求的header里面要添加两个自定义的header


GET http://localhost:8080/api/v1/users
Accept: */*
Content-Type: application/json
Authorization: token:21232f297a57a5a743894a0e4a801fc3
Username: admin

增加了两个自定义字段 Authorization和Username
在请求时 我看到 network里面出现了两次请求记录 第一次是一个 OPTION请求 状态码200第二次是我的get请求 状态码 401


可以这边后端已经做了CORS处理。为何还出现这种情况呢。
我们一般在项目里解决跨域问题简单说会采取方案有

  1. 使用ajax直接跨域访问

2.使用JsonP。实际使用时,由于JsonP向Server提交URL的长度限制在8000字符,超过了则被浏览器拒绝,因此不采用。

对于第一种方案,后端需要做的工作是:
接口允许允许跨域请求:


header('Access-Control-Allow-Origin:*'); //支持全域名访问,不安全,部署后需要限制为R.com
header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); //支持的http动作
header('Access-Control-Allow-Headers:x-requested-with,content-type'); //响应头 请按照自己需求添加。

前端发起跨域请求:就是正常的$.ajax请求即可。我的项目用的vue全家桶 用的axios 发送的请求


// request拦截器
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['Authorization'] =`token:${getToken()}`
config.headers['Username'] =`getUsername()`
}
return config
},
error => {
// Do something with request error
Promise.reject(error)
}
)

但是,碰到个问题,国内网站基本没有讲,就是option请求问题。

在正式跨域的请求前,浏览器会根据需要,发起一个“PreFlight”(也就是Option请求),用来让服务端返回允许的方法(如get、post),被跨域访问的Origin(来源,或者域),还有是否需要Credentials(认证信息)
三种场景:

  1. 如果跨域的请求是Simple Request(简单请求 ),则不会触发“PreFlight”。Mozilla对于简单请求的要求是:

以下三项必须都成立:

  1. 只能是Get、Head、Post方法
  2. 除了浏览器自己在Http头上加的信息(如Connection、User-Agent),开发者只能加这几个:Accept、Accept-Language、Content-Type、。。。。
  3. Content-Type只能取这几个值:

application/x-www-form-urlencoded
multipart/form-data
text/plain

XHR对象对于HTTP跨域请求有三种:简单请求、Preflighted 请求、Preflighted 认证请求。简单请求不需要发送OPTIONS嗅探请求,但只能按发送简单的GET、HEAD或POST请求,且不能自定义HTTP Headers。Preflighted 请求和认证请求,XHR会首先发送一个OPTIONS嗅探请求,然后XHR会根据OPTIONS请求返回的Access-Control-*等头信息判断是否有对指定站点的访问权限,并最终决定是否发送实际请求信息。
那么我的get请求呢?
原来,产生 OPTIOINS 请求的原因是:自定义 Headers 头信息导致的。
浏览器会去向 Server 端发送一个 OPTIONS 请求,看 Server 返回的 "Access-Control-Allow-Headers" 是否有自定义的 header 字段。因为我之前没有返回自定义的字段,所以,默认是不允许的,造成了客户端没办法拿到数据。

那么这样 的话如果后端是python的话


rom corsheaders.defaults import default_headers CORS_ALLOW_HEADERS = default_headers + (
'Authorization,Username'
)

前端这边如果用的vue全家桶 可以这样搞一下


module.exports = {
NODE_ENV: '"development"',
ENV_CONFIG: '"dev"',
BASE_API: '"/proxy"'
}


'/proxy': {
target: 'http://jupiter.dev.grdoc.org/',
changeOrigin: true,
pathRewrite: {
'^/proxy': '/'
},
sesure:false
}

开发环境这样搞一下 应该就不算跨域了。


我是山豆 我的gitHub

一次跨域请求出现 OPTIONS 请求的问题及解决方法的更多相关文章

  1. http跨域时的options请求

    1.背景 在前后端分离的项目中经常会遇到跨域请求的问题,如果没有进行跨域配置,会浏览器请求失败.我一般采用两种解决方案: 1.采用nginx进行转发,是前后端服务处于同一个域下面,从根本上避免跨域问题 ...

  2. 跨域GET、POST请求

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

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

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

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

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

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

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

  6. Laravel dingo,HTTP的请求头(accept)无法携带版本号的解决方法

    Laravel dingo,HTTP的请求头(accept)无法携带版本号的解决方法  2017年9月6日  原创分享  zencodex  使用 Laravel dingo 做api开发时,涉及 A ...

  7. ios/iphone手机请求微信用户头像错位BUG及解决方法

    转:http://www.jslover.com/code/527.html ios/iphone手机请求微信用户头像错位BUG及解决方法 发布时间:2014-12-01 16:37:01 评论数:0 ...

  8. 记一次 CORS 跨域请求出现 OPTIONS 请求的问题及解决方法

    今天前后端在联调接口的时候,发生了跨域请求资源获取不到的问题. 首先说明下跨域问题的由来.引自HTTP 访问控制 的一段话: 当 Web 资源请求由其它域名或端口提供的资源时,会发起跨域 HTTP 请 ...

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

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

随机推荐

  1. Android - 显示手机执行的Activity

    显示手机执行的Activity 本文地址:http://blog.csdn.net/caroline_wendy 手机中,须要调试程序的界面,能够高速进行定位,使用Android开发工具ADB(And ...

  2. oracle如何获得新插入记录的id

    .对于提交(最后一次操作commit了)的话可以查询那个提交段 SELECT 列名1,列名2…… FROM 表名 VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAX ...

  3. 如何查看linux版本 如何查看LINUX是多少位

    一.如何得知自己正在使用的linux是什么版本呢,下面的几种方法将给你带来答案! 1. 查看内核版本命令: 1) [root@q1test01 ~]# cat /proc/version Linux ...

  4. 微信小程序(应用号)开发新闻客户端的实战课程

    摘要: 本实例将演示从零开发一个微信应用号的过程,页面轮播与跳转传值,实现单元格自定义布局,全部源码可通过github下载. 下载最新版的微信小程序开发工具,目前是v0.9.092300 下载地址:h ...

  5. C/C++内存管理详解(转)

    内存分配方式 简介 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动 ...

  6. node.js ----NPM使用介绍

    NPM 使用介绍 NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种: 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从 ...

  7. Lua学习五----------Lua循环

    © 版权声明:本文为博主原创文章,转载请注明出处 1.循环类型 1.1 while循环 - 语法:while(condition) do ...<执行语句> end - 解析:判断cond ...

  8. ORACLE经常使用系统查询

     1  查询系统全部对象 SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, CREATED, LAST_DDL_TIME, TIMESTAMP, STATUS FRO ...

  9. Delphi列表控件TListView定位到某一行。

    ListView1.Item[100].Focused = true; //定位到索引为100的行ListView1.Item[100].Selected = true; ListView1.Item ...

  10. Java8中 Date和LocalDateTime的相互转换

    一.在Java 8中将Date转换为LocalDateTime 方法1: 将Date转换为LocalDatetime,我们可以使用以下方法: 1.从日期获取ZonedDateTime并使用其方法toL ...