一位好友告诉我,博客无法评论了
之前确实是改过一点页面上的东西,但是经过Chrome调试并没有发现有什么报错
我万万没想到,居然是nginx的锅

什么是Referer?

来自百度百科的介绍:

HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。

分析

在tale博客系统中,有关于Http_Referer的验证

        //验证Referer是否为空
        if (StringKit.isBlank(Referer)) {
            return RestResponse.fail(ErrorCode.BAD_REQUEST);
        }
        //验证Referer是否来源于本机
        if (!Referer.startsWith(Commons.site_url())) {
            return RestResponse.fail("非法评论来源");
        }

根据问题情况,可以确定是这里的代码导致的:Referer为空

从用户的访问流程来分析

用户浏览器 -> nginx -> jetty -> Controller -> ...

js的执行包括请求的提交都是正常的,问题不在客户端、通过本地项目http访问也没有问题,问题不在项目上、通过https访问会出现问题,说明问题出在nginx上

问题原因

通过Chrome调试,发现Http_Referer是存在且正确的,然而控制层却没有收到,简单的说就是Referer在nginx传递给项目时被传掉了

通过查询资料发现:
根据RFC文档:HTTP/1.1: Security Considerations

Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if the referring page was transferred with a secure protocol.

在Https -> Http的过程中Referer是不被传递的,而在 Https -> Https 或 Http -> Https 则没有这样的问题

用户与nginx是https,而nginx与jetty是http(反代),所以Referer就没了

解决方案

nginx接收的请求是有Referer的,只是之后通过Http与Jetty通讯时没有传递Referer罢了

所以要解决这个问题,只需要设置nginx与jetty的http请求头带有Referer即可

proxy_set_header Referer $http_referer;

参考

从Https跳转到Http时不传递


Keeping frank is the easiest way to keep it simple.