网易技术分享:Nginx缓存引发的跨域惨案
推荐:更多技术团队分享文章 关注:MAYOU18技术专栏
1. 前言
贵金属wap版直播间上线后,偶尔有用户反馈,在进入wap直播间的时候,出现空白页面,但是重新刷新又可以正常显示了。我们曾一度认为是网络请求异常或兼容问题,直到开发PC版直播间,在进行调试中,同样遇到了“白屏”问题,才引起了足够重视,并进行了问题跟踪与分析。现在跟大家分享一下,这种偶然现象出现的原因。
我们的直播间落地页在fa.163.com 系统,而直播间内容,是通过 向直播间系统 qz.fa.163.com 发起Ajax请求获取的。在出现“白屏”的时候,可以通过浏览器的调试窗口,可以看到出现下面的报错:

2. 问题分析
从上述错误提示文案中可以看到,问题首先和 跨域 有关。
何为跨域
从字面上理解为“跨域名”,
浏览器不能执行其他网站的脚本,然而,跨域不仅仅局限于域名这一项。只要协议、域名、端口有任何一个不同,都被当作是不同的域。 这是由于>同源策略的限制,从一个域上加载的脚本不允许访问另外一个域的文档属性。虽然在浏览器中,<script>、<img>、<iframe>、<link>等标签都>可>以加载跨域资源,而不受同源限制,但浏览器会限制脚本中发起的跨域请求。比如,使用 XMLHttpRequest 对象和Fetch发起 HTTP 请求就必须遵守同源策略。同源策略/SOP(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。SOP要求两个通讯地址的协议、域名、端口号必须相同,否则两个地址的通讯将被浏览器视为不安全的,并被block下来。
举个例子:从贵金属主站 http://fa.163.com 发起请求访问以下url:
解决跨域
在实际应用中有多种方式来解决跨域问题,相信在实践中都会用到其中的某些方案:
1.JSONP (无状态连接,不能获悉连接状态和错误事件,而且只能走GET的形式)
2.iframe形式
3.服务器代理
页面直接向同域的服务端发请求,服务端进行跨域处理或爬虫后,再把数据返回给客户端页。
4.CORS
CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就>是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。目前,所有浏览器都支持该功能,IE浏览器不能低>于IE10。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏>览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
CORS方式实现:
浏览器在发出CORS请求时会在头信息之中增加一个Origin字段;
后端返回代码中增加三个字段
1 |
header(“Access-Control-Allow-Origin”:“”); // 必选 允许所有来源访问 |
5.nginx反向代理
nginx是一个高性能的web服务器,常用作反向代理服务器。nginx作为反向代理服务器,就是把http请求转发到另一个或者一些服务器上。通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以。
为了解决跨域问题,我们选择方案d , 在直播间的过滤器中,统一添加了如下代码:
1 |
@Override |
从错误提示文案中,我们还可以看到错误提示的关键点 “http://fa.163.com” that is not equal to the supplied origin. Origin ‘https://fa.163.com' is therefore not allowed access.
目前我们的系统同时支持http访问和https访问,但是为什么使用 http访问 ,返回的header中却是 https 协议呢?
通过多次模拟,确认出现问题的请求中,Request URL使用的协议和 response返回的headers中的 Access-Control-Allow-Origin 中的 协议确实不一致,且还有一个特性,X-Cached 为 HIT,如下图:

命中了缓存的请求,出现了协议不一致?
突然想到,这个接口,我们配置了nginx 缓存,那必然和nginx缓存有关了。
Nginx 缓存
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器。
首先从源服务器(内部网络上的web服务器)上获取内容,然后把内容返回给用户,同时,也会把内容保存到代理服务器上一份,这样日后再接收同样的信息请求时,他会把本地缓存里的内容直接发给用户,以此减少后端web服务器的压力,提高响应速度。这其实就是缓存服务器所实现的功能。如下图所示。
进入直播间后,首先需要查询直播内容是否有更新,而这个接口客户端会以5s间隔轮询,为了减少tomcat的压力,我们配置了nginx缓存。配置如下:

其中:
proxy_cache_methods: 用来设置HTTP哪些方法会被缓存,直播间接口配置了GET、HEAD、POST;
proxy_cache_valid: 用来设置对不同HTTP状态码的不同缓存时间。直播间接口配置了对于 返回值为200的状态码,缓存5秒;
proxy_cache_min_uses: 用来设置多少次访问后,应答值会被缓存,配置为3次;
proxy_cache_key: 设置Web缓存的key
proxy_cache: 用来设置哪个缓存区将被使用,并定义缓存区的名称
通过上述配置,我们可以看到 proxy_cache_key 配置中,只配置了host + uri + 参数,但没有配置协议,所以无论用http访问,还是https访问,只要被缓存后,返回的内容都是一样的,而不会区分http或https。从而引起了跨域问题。
至此,问题分析完毕。
3. 问题解决
跟运维同学沟通后,通过修改nginx配置,将协议类型scheme加入到缓存查找的判断参数中,配置如下。

问题得到了解决。
4. 总结
上述“惨案” ,是 跨域、nginx缓存、http/https协议 这三种条件同时出现引发的。
如果不涉及跨域,混用 http/https协议 + nginx缓存,其实也是没有问题的。但是一旦出现了跨域使用,必须 在nginx 缓存配置中,配置 scheme + host + uri + 参数。
网易技术分享:Nginx缓存引发的跨域惨案的更多相关文章
- nginx反向代理实现跨域请求
nginx反向代理实现跨域请求 跨域请求可以通过JSONP实现,缺点是需要修改被请求的服务器端代码进行配合,稍显麻烦通过在自己服务器上配置nginx的反向代理,可以轻松实现跨域请求 思路 示例服务器A ...
- chrome浏览器的跨域设置 Google Chrome浏览器下开启禁用缓存和js跨域限制--disable-web-security
chrome用户默认路径 Win7:C:\Users\[用户名]\AppData\Local\Google\Chrome\User Data\XP:C:\Documents and Settings\ ...
- Nginx通过CORS实现跨域
Nginx通过CORS实现跨域 2016-09-01 10:33 阅读 9.4k 评论 0 社区广播:运维派(Yunweipai.com)是国内最早成立的IT运维社区,欢迎大家投稿,让运维人不再孤寂的 ...
- Nginx通过CORS实现跨域(转)
如果前端有nginx方向代理,跨域配置在前端反向代理nginx上 要做跨域域名限制 什么是CORS CORS是一个W3C标准,全称是跨域资源共享(Cross-origin resource shari ...
- 一个JS引发的跨域问题
忽然遇上跨域错误. 我们有张页面,使用了EXT.js,在本地运行正常,部署到服务器上,出不来数据.F12调试,提示有跨域错误? XMLHttpRequest cannot load http://19 ...
- VUE线上通过nginx反向代理实现跨域
1.NGINX反向代理实现跨域 VUE代码中配置参考上一篇文章 nginx配置,红色框线内: 代码: location /list { proxy_set_header X-Real-IP $remo ...
- nginx/apache静态资源跨域访问问题详解
1. apache静态资源跨域访问 找到apache配置文件httpd.conf 找到这行 #LoadModule headers_module modules/mod_headers.so把#注释符 ...
- ASP.NET Core 缓存技术 及 Nginx 缓存配置
前言 在Asp.Net Core Nginx部署一文中,主要是讲述的如何利用Nginx来实现应用程序的部署,使用Nginx来部署主要有两大好处,第一是利用Nginx的负载均衡功能,第二是使用Nginx ...
- 【微信支付】分享一个失败的案例 跨域405(Method Not Allowed)问题 关于IM的一些思考与实践 基于WebSocketSharp 的IM 简单实现 【css3】旋转倒计时 【Html5】-- 塔台管制 H5情景意识 --飞机 谈谈转行
[微信支付]分享一个失败的案例 2018-06-04 08:24 by stoneniqiu, 2744 阅读, 29 评论, 收藏, 编辑 这个项目是去年做的,开始客户还在推广,几个月后发现服务器已 ...
随机推荐
- 洛谷P4199 万径人踪灭(manacher+FFT)
传送门 题目所求为所有的不连续回文子序列个数,可以转化为回文子序列数-回文子串数 回文子串manacher跑一跑就行了,考虑怎么求回文子序列数 我们考虑,如果$S_i$是回文子序列的对称中心,那么只要 ...
- 拓扑排序复习——Chemist
一.基本算法 拓扑序列:对于一张有向图,求一个序列ai若对于每一条边(u,v),都满足au<=av ,则称这个序列为这张有向图的拓扑序列,一张图可能有多个拓扑序列. 求拓扑序列:找到入度为0的点 ...
- Charles对移动APP抓包(https)
1.下载安装Charles 2.设置代理 (1)查看默认端口:Proxy->Proxy Settings 在这个页面会看到HTTP Proxy的默认端口是8888 (2)查看当前电脑的IP:H ...
- vue中methods中的方法闭包缓存问题
vue中methods中的方法闭包缓存问题 问题背景 需求描述 在路由的导航栏中需要, 判断是否为第一次点击 需要一个标志位来记录是否点击过 现状: 这个标志位只在一个函数中用过.不希望存放全局 希望 ...
- JavaScript入门2
5.document对象:Document对象是window对象的一个对象属性,代表浏览器窗口中装载的整个HTML文档.文档中的每个HTML元素对应着JavaScript对象. 因为document代 ...
- RHEL 6.5----haproxy实现负载均衡
主机名 IP master 192.168.30.130 node-1 192.168.30.131 node-2 192.168.30.132 在master上安装 [root@master ~]# ...
- Suricata的总体架构
Suricata的总体架构 报文检测系统通常四大部分,报文获取.报文解码.报文检测.日志记录:suricata不同的功能安装模块划分,一个模块的输出是另一个模块的输入,suricata通过线程将模块 ...
- 分享几个自己喜欢的前端UI框架
http://www.layui.com/ http://element-cn.eleme.io/#/zh-CN/component/installation
- C#之九大视图
本节向大家介绍一下有关UML视图方面的内容,UML视图共有9种,它们之间有什么区别和联系呢,下面就让我们一起来学习吧,相信通过本节的介绍你一定会有不少收获. UML视图 UML总共提供了9种视图,这些 ...
- 外文翻译 《How we decide》被情感愚弄 第三节
本科论文答辩终于结束啦,一切都要继续回到正轨. 这是第三章章最后一节 书的导言 本章第二节 本章第一节 "信用卡是我的敌人."Herman Palmer这样说到.在平日,Herma ...

