ITPub博客

首页 > > > 一则 Nginx 缓存引发的跨域惨案~

一则 Nginx 缓存引发的跨域惨案~

作者:u_453e1a12781dea 时间:2017-08-28 16:38:32 0 删除 编辑

点击蓝色字关注"CU技术社区" 一起玩耍哦~

作者:张捷

原文地址:http://tech.lede.com/2017/07/21/rd/server/crossdomain/


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”:“”);           // 必选 允许所有来源访问

  2. header(“Access-Control-Allow-Credentials”:“true”);  // 可选 是否允许发送 cookie

  3. header(“Access-Control-Allow-Method”:“POST,GET”);   // 可选 允许访问的方式


nginx 是一个高性能的 web 服务器,常用作反向代理服务器。nginx 作为反向代理服务器,就是把 http 请求转发到另一个或者一些服务器上。通过把本地一个 url 前缀映射到要跨域访问的 web 服务器上,就可以。

为了解决跨域问题,我们选择方案 d , 在直播间的过滤器中,统一添加了如下代码:


  1. <a href="http://www.jobbole.com/members/wx610506454">@Override</a>

  2.   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

  3.    // 加入响应头

  4.    String origin = request.getHeader("Origin");

  5.    if("http://fa.163.com".equals(origin) || "https://fa.163.com".equals(origin) ) {

  6.        response.addHeader("Access-Control-Allow-Origin", origin);

  7.        response.addHeader("Access-Control-Allow-Credentials", "true");

  8.    }

  9.    return true;

  10. }

 

从错误提示文案中,我们还可以看到错误提示的关键点 “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 缓存。配置如下:


其中:


  1. proxy_cache_methods: 用来设置 HTTP 哪些方法会被缓存,直播间接口配置了 GET、HEAD、POST;

  2. proxy_cache_valid:    用来设置对不同 HTTP 状态码的不同缓存时间。直播间接口配置了对于返回值为 200 的状态码,缓存 5 秒;

  3. proxy_cache_min_uses: 用来设置多少次访问后,应答值会被缓存,配置为 3 次;

  4. proxy_cache_key:      设置 Web 缓存的 key

  5. 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 + 参数。


与 100 + 技术大牛面对面

SACC2017

作为国内最受欢迎的架构师盛会,2017 第九届中国系统架构师大会 (SACC) 将于将于 2017 年 10 月 19-21 日在北京新云南皇冠假日酒店震撼来袭。


大会以 “云智未来” 为主题,云集国内外顶级专家,围绕云计算、人工智能、大数据、移动互联网、产业应用等热点领域展开技术探讨与交流。本届大会共设置 2 大主会场,18 个技术专场;邀请来自互联网、金融、制造业、电商等多个领域,100 余位技术专家及行业领袖来分享他们的经验;并将吸引 4000 + 人次的系统运维、架构师及 IT 决策人士参会,为他们提供最具价值的交流平台。

点击“阅读原文”与100+技术大牛面对面,立享购票7.8折优惠~

原文作者:;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-07-17

  • 博文量
    1982
  • 访问量
    17914