我的踩坑之旅-跨域问题引发bug
发布日期:2021-10-23 14:13:09 浏览次数:9 分类:技术文章

本文共 3003 字,大约阅读时间需要 10 分钟。

场景:

        由于业务原因需要在请求中添加一个信息表明请求的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配置响应头)作个示例,具体如下:

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

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

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

转载于:https://www.cnblogs.com/dhh-blog/p/8409289.html

转载地址:https://blog.csdn.net/weixin_30588827/article/details/98927450 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java设计模式之抽象工厂模式
下一篇:http请求拦截器

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年03月15日 10时51分26秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

jquery查找div下第一个input_jquery查找div元素第一个元素id 2019-04-21
如何修改手机屏幕显示的长宽比例_屏幕分辨率 尺寸 比例 长宽 如何计算 2019-04-21
mysql 的版本 命名规则_MySQL版本和命名规则 2019-04-21
no java stack_Java Stack contains()用法及代码示例 2019-04-21
java动态代码_Java Agent入门学习之动态修改代码 2019-04-21
python集合如何去除重复数据_Python 迭代删除重复项,集合删除重复项 2019-04-21
iview 自定义时间选择器组件_Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能... 2019-04-21
java 验证码校验_JavaWeb验证码校验功能代码实例 2019-04-21
java多线程初学者指南_Java多线程初学者指南(4):线程的生命周期 2019-04-21
java进程user是jenkins_java 学习:在java中启动其他应用,由jenkins想到的 2019-04-21
java添加资源文件_如何在eclipse中将资源文件夹添加到我的Java项目中 2019-04-21
java的三种修饰符_3分钟弄明白JAVA三大修饰符 2019-04-21
mysql source skip_redis mysql 中的跳表(skip list) 查找树(btree) 2019-04-21
java sun.org.mozilla_maven编译找不到符号 sun.org.mozilla.javascript.internal 2019-04-21
php curl 输出到文件,PHP 利用CURL(HTTP)实现服务器上传文件至另一服务器 2019-04-21
PHP字符串运算结果,PHP运算符(二)"字符串运算符"实例详解 2019-04-21
PHP实现 bcrypt,如何使php中的bcrypt和Java中的jbcrypt兼容 2019-04-21
php8安全,PHP八大安全函数解析 2019-04-21
php基础语法了解和熟悉的表现,PHP第二课 了解PHP的基本语法以及目录结构 2019-04-21
matlab中lag函数用法,MATLAB movavg函数用法 2019-04-21