场景:

由于业务原因需要在请求中添加一个信息表明请求的source,经过一轮方案的评审,大家共同决定把这source信息存放在消息header中。前端小伙伴听完之后心里暗自偷笑:就一行的代码的事,请求的时候在消息头中添加source:xxxx,这么轻松。然后也没有测试就直接发布了。刚发布没多久,用户纷纷过来投诉各种页面打不开。

cause:

用户刚投诉,小伙伴们纷纷跑到后台抓取日志查看,但是啥也没有。只能亲测了页面了,一打开页面立马在console上看到各种红点,全显示各种跨域问题。当时就纳闷了,项目中有考虑跨域问题呀,后台配置了CORSFilter,以前一直也没有什么问题呀。经过各种确认之后才发现是由于前端加了自定义消息头的原因。

跨域流程具体分析:

说到跨域,首先有已个关键词:同源性。同源性指的是当前页面的协议号,域名,端口号与所请求的资源的协议号,域名,端口号保持一致。浏览器为什么要这么做呢?这是从安全方面考虑,防止XSS攻击。但是现实场景中,很多情况又不得不跨域请求。这该怎么办呢?W3C增加了CORS标准,这个标准允许浏览器向跨源服务器发出XMLHttpRequest请求。CORS需要浏览器和服务器同时支持。在跨域请求中可以分为简单请求和非简单请求,简单请求指的是——请求方法为GET,POST,HEAD,请求响应头只能为:Accept,Accept-Language,Last-Event-ID,Content-type,且Content-type的值只能为application/x-www-form-urlencoded、multipart/form-data、text/plain。其它的请求都属于非简单请求。

简单请求:简单请求相对于非跨域请求在请求header中添加了一个origin头,表明本次请求的来源,服务器收到请求,根据origin头判断是否支持本次请求,如果支持返回响应结果,并在响应中添加了一个Access-Control-Allow-Origin头,如果服务器不支持本次请求,会返回一个正常的http响应,正常的响应指的是http status code正常,但是没有响应内容。

非简单请求:非简单请求相对于非跨域请求增加了一次请求,这次请求俗称“预检”请求,这个请求的request method 是OPTIONS方法,header头中有origin和Access-Control-Request-Header,origin头的意义跟上文的一致,Access-Control-Request-Header头包含的信息是本次请求(真实请求,不是指嗅探请求)的所有请求头。这个请求顾名思义就是嗅探下服务器是否支持本次请求。嗅探的内容包括:服务器是否支持真实请求的request method,是否支持真实请求的消息头(具体是从Access-Control-Request-Header取出值,然后跟服务器配置的可接受消息头进行比对),查看当前网页所在的域名是否在服务器的许可名单中(查看origin头中的值是不是在服务器的允许域名列表中),若服务器不支持本次真实请求的话,嗅探请求会返回403,真实请求也不会发生了。

服务器端的配置:以上讨论的是浏览器端做的操作,当然那些操作用户无法感知,程序猿也不需要特别开发,一切都是浏览器自主完成,目前大部分浏览器都支持CORS。CORS需要浏览器和服务器共同配合完成,那服务器端需要配置什么呢?总结起来就那么几点:哪些域名是服务器认可得,哪些请求方法是服务器认可的,哪些请求头是服务认可的,是否允许设置cookie。下面利用spingMVC的CORSFilter来配置服务器(不止这一种方案,还有其他诸如在Nginx配置响应头)作个示例,具体如下:

<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
//配置支持的方法
<param-name>cors.supportedMethods</param-name>
<param-value>GET,POST, HEAD, PUT, DELETE</param-value>
</init-param>
<init-param>
//配置支持的消息头
<param-name>cors.supportedHeaders</param-name>
<param-value>Accept,Origin, Authorization, X-Requested-With, Content-Type, Last-Modified</param-value>
</init-param>
<init-param>
//配置响应结果的暴露的消息头
<param-name>cors.exposedHeaders</param-name>
<param-value>Set-Cookie</param-value>
</init-param>
<init-param>
//是否允许cookie
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

服务器端配置之后,就可以进行“预检”请求了,“预检“”请求之后,你会发现响应消息头中相对于非跨域请求会增加几个消息头:Access-Contol-Allow-Origin(表明服务器允许的消息来源域),Access-Control-Allow-Method(表明服务器允许的请求方法),Access-Control-Allow-Header(表明服务器允许的请求头),Access-Control-Allow-Credentials(是否允许Cookie,若不允许,前端就拿不到cookie了),浏览器收到这几个头之后,觉得真实请求满足这些条件,接下来就会发起真实的请求了。

总结:回到最开始的bug问题,这个问题是因为前端开发人员在请求中自定义了一个消息头source,不在简单请求的范围内,属于非简单请求,在发起“预检”请求时,由于后台CORSFilter中没有配置允许该请求头,倒致“预检”请求403。

我的踩坑之旅-跨域问题引发bug的更多相关文章

  1. Flask框架踩坑之ajax跨域请求

    业务场景: 前后端分离需要对接数据接口. 接口测试是在postman做的,今天才开始和前端对接,由于这是我第一次做后端接口开发(第一次嘛,问题比较多)所以在此记录分享我的踩坑之旅,以便能更好的理解,应 ...

  2. 我的微信小程序入门踩坑之旅

    前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...

  3. vue+ vue-router + webpack 踩坑之旅

    说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案   老司机可以忽略下面的内容了 1)起因  考虑到数据分离的问题  因为server是express搭的   自然少 ...

  4. 微信小程序之mpvue+iview踩坑之旅

    因为之前参照微信的原生的文档写过一些小程序的demo,写的过程比较繁琐,后来出了美团的mpvue,可以直接使用vue开发,其他的不作对比,这篇文章记录一下踩坑之旅. 参照mpvue http://mp ...

  5. vue踩坑之旅 -- computed watch

    vue踩坑之旅 -- computed watch 经常在使用vue初始化组件时,会报一些莫名其妙的错误,或者,数据明明有数据,确还是拿不到,这是多么痛苦而又令人忍不住抓耳挠腮,捶胸顿足啊 技术点 v ...

  6. Python踩坑之旅其一杀不死的Shell子进程

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...

  7. Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...

  8. [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...

  9. CentOS7使用tar.gz包安装MySql的踩坑之旅

    由于客户的CentOS服务器没有安装yum工具,只能通过下载tar.gz包安装mysql,于是跟着万能的百度开启了漫漫踩坑之旅: 1.下载mysql-5.6.33-linux-glibc2.5-x86 ...

随机推荐

  1. 二叉树——遍历篇(递归/非递归,C++)

    二叉树--遍历篇 二叉树很多算法题都与其遍历相关,笔者经过大量学习.思考,整理总结写下二叉树的遍历篇,涵盖递归和非递归实现. 1.二叉树数据结构及访问函数 #include <stdio.h&g ...

  2. Nginx概述和安装(1)

    一.Nginx概述 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 I ...

  3. (๑•̀ㅂ•́)و✧随笔总目录ヾ(≧▽≦*)o

    SSM整合进阶篇 日常手记 开源博客My Blog系列 短信接口攻击事件 读书笔记 SSM整合优化篇 SSM整合基础篇 SSM整合进阶篇 Spring+SpringMVC+MyBatis+easyUI ...

  4. cs231n spring 2017 lecture7 Training Neural Networks II 听课笔记

    1. 优化: 1.1 随机梯度下降法(Stochasitc Gradient Decent, SGD)的问题: 1)对于condition number(Hessian矩阵最大和最小的奇异值的比值)很 ...

  5. Codefoces 723A The New Year: Meeting Friends

    A. The New Year: Meeting Friends time limit per test:1 second memory limit per test:256 megabytes in ...

  6. HDU5135 dfs搜索 枚举种数

    Little Zu Chongzhi's Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 ...

  7. Cup(二分)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2289 hdu_2289:Cup Time Limit: 3000/1000 MS (Java/Othe ...

  8. PL/SQL 一个数据对象一个事务(rollback,submit)

    /*********************************************** 一个数据对象一个事务(且记录错误信息到处理对象) ************************** ...

  9. 慕课网-前端JavaScrpt基础面试技巧-学习笔记

    章节目录: JS基础知识(上)--讲解 JS 基础语法相关的面试题,分析原理以及解答方法.这一章节讲解了基础知识的第一部分:变量的类型和计算.以及JS "三座大山" -- 原型.作 ...

  10. Google PageSpeed Tools 性能测试分析

    今天给大家介绍下一个工具:Google PageSpeed Tools,根据官方的介绍,简单梳理如下: Page Speed Insights能针对移动设备和电脑设备衡量网页的性能.该工具会抓取网址两 ...