一位好友告诉我,博客无法评论了
之前确实是改过一点页面上的东西,但是经过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;
参考
Q.E.D.