我的踩坑之旅-跨域问题引发bug
场景:
由于业务原因需要在请求中添加一个信息表明请求的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的更多相关文章
- Flask框架踩坑之ajax跨域请求
业务场景: 前后端分离需要对接数据接口. 接口测试是在postman做的,今天才开始和前端对接,由于这是我第一次做后端接口开发(第一次嘛,问题比较多)所以在此记录分享我的踩坑之旅,以便能更好的理解,应 ...
- 我的微信小程序入门踩坑之旅
前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...
- vue+ vue-router + webpack 踩坑之旅
说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案 老司机可以忽略下面的内容了 1)起因 考虑到数据分离的问题 因为server是express搭的 自然少 ...
- 微信小程序之mpvue+iview踩坑之旅
因为之前参照微信的原生的文档写过一些小程序的demo,写的过程比较繁琐,后来出了美团的mpvue,可以直接使用vue开发,其他的不作对比,这篇文章记录一下踩坑之旅. 参照mpvue http://mp ...
- vue踩坑之旅 -- computed watch
vue踩坑之旅 -- computed watch 经常在使用vue初始化组件时,会报一些莫名其妙的错误,或者,数据明明有数据,确还是拿不到,这是多么痛苦而又令人忍不住抓耳挠腮,捶胸顿足啊 技术点 v ...
- Python踩坑之旅其一杀不死的Shell子进程
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...
- Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...
- [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...
- CentOS7使用tar.gz包安装MySql的踩坑之旅
由于客户的CentOS服务器没有安装yum工具,只能通过下载tar.gz包安装mysql,于是跟着万能的百度开启了漫漫踩坑之旅: 1.下载mysql-5.6.33-linux-glibc2.5-x86 ...
随机推荐
- SQLServer 创建服务器和数据库级别审计
概述 在上一篇文章中已经介绍了审计的概念:本篇文章主要介绍如何创建审计,以及该收集哪些审核规范. 一.常用的审核对象 1.1.服务器审核对象 1.FAILED_LOGIN_GROUP( Audit L ...
- Spring Boot快速入门(二):http请求
原文地址:https://lierabbit.cn/articles/4 一.准备 postman:一个接口测试工具 创建一个新工程 选择web 不会的请看Spring Boot快速入门(一):Hel ...
- 单张滑动tab 组件
/* CSS重置 * */ body, ul, ol { margin: 0px; padding: 0px; } .flash { width: 300px; height: 420px; posi ...
- 使用三种方法求解前N个正整数的排列
本篇博文给大家介绍前N个正整数的排列求解的三种方式.第一种是暴力求解法:第二种则另外声明了一个长度为N的数组,并且将已经排列过的数字保存其中:第三种方式则采用了另外一种思路,即首先获取N个整数的升序排 ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)
前言 上一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](二)>我们通过如下操作: 创建实体及工具类 创建Re ...
- 如何让一个DIV水平,垂直方向都居中于浏览器?
<style type="text/css"><!-- div {position:absolute;top:50%;left:50%;margin:-150px ...
- BZOJ 2219: 数论之神
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2219 N次剩余+CRT... 就是各种奇怪的分类讨论.. #include<cstrin ...
- poj1258prim算法
/*poj 1258 *题意:有若干个农场,现需要将各个农场用光纤连接起来,各个农场之间连接的光纤长度也许不同, *要求求出使得将所有农场连接起来的最短光线长度 *算法分析:使用矩阵将各个农场之间的光 ...
- 分布式监控系统--zabbix
1Zabbix简介 Zabbix 是一个企业级的分布式开源监控方案. 2.监控系统架构 C/S架构 客户端/服务器端,这种架构适合规模较小,处于同一地域的环境 C/P/S 客户端/代理端/服务器端/, ...
- js判断是否为ie浏览器
之前在开发时遇到浏览器的兼容性问题,涉及到对ie浏览器的判断.现在此做个笔记. 这里我以函数的形式来判断,在用的时候直接调用即可. var isIE = !!window.ActiveXObject ...