这几天配置Nginx服务器的反向代理,使用HTTPS代理Laravel的HTTP应用出现了一点小问题,经过一番研究,特地记录下来。
使用场景
反向代理的概念不多做解释,此处应用反向代理主要原因如下:
- 应用服务器不必暴露在公网,躲在防火墙后,通过内网连接代理服务器(proxy server);
- DNS设置简单,因为有两个不同应用服务器,对应不同的子域名(a.example.com, b.example.com),只需设置DNS
*.example.com
到代理服务器IP即可; - SSL证书管理方便,只需申请一个通配符的证书
*.example.com
配置在代理服务器。
环境
系统环境都是Ubuntu 18.04.2,服务器都是使用Nginx,代理服务器配置SSL,使用HTTPS对外访问(HTTP强制跳转到HTTPS),应用服务器使用Laravel,HTTP对内网访问。
配置
应用服务器配置
应用服务器的nginx照常配置即可,可以设置server_name
为对应的域名。
代理服务器配置
代理服务器从网上抄来一份,主要是设置proxy_pass
,下面只是location block:
1 | location / { |
注意要加 proxy_set_header X-Forwarded-Proto $scheme
这一条,让后面被代理的应用服务器知道对应的协议是什么,这样应用服务器生成url(如css,js文件)使用相应的协议。如果代理服务器确定使用https,那$scheme
替换成https
也可以。
http://nginx.org/en/docs/http/ngx_http_core_module.html#var_scheme
问题
本以为这样就搞定了,但是在用域名测试的时候发现网站不能正常加载,浏览器有如下错误:
1 | Mixed Content: The page at '<URL>' was loaded over HTTPS, but requested an insecure stylesheet '<URL>'. This request has been blocked; the content must be served over HTTPS. |
在页面中混用了HTTPS和HTTP,浏览器会block掉不安全的HTTP链接。而HTTP链接主要是用laravel的asset
生成的css, js文件,css文件没有加载上,所以就不能正常加载了。
多方查询,有推荐使用proxy_redirect
来替换HTTP为HTTPS,但是试用不成功。
也有说这些资源文件用uri路径来表示,\css\example.css
这样,不带协议。
或者页面增加一个meta,让HTTP升级为安全的HTTPS:
1 | <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" /> |
这样在生产环境没问题,但是需要改动很多代码,而且开发、测试环境也需要ssl证书,很不方便。
在查询到几篇文章中,有提到后端是tomcat,需要修改tomcat的配置来接受X-Forwarded-Proto
这个Header来处理。我思考是不是laravel也需要类似设置,google一下发现了这个:
https://laravel.com/docs/5.5/requests#configuring-trusted-proxies
When running your applications behind a load balancer that terminates TLS / SSL certificates, you may notice your application sometimes does not generate HTTPS links. Typically this is because your application is being forwarded traffic from your load balancer on port 80 and does not know it should generate secure links.
Laravel从5.5开始,内置了一个 TrustProxies
模块来解决这个问题,专门应对使用了Load Balancer等情况。
所以按照文档,修改 protected $proxies = '**'
,因为应用服务器在内网,所以改成**
也无所谓。
Laravel 5.5之前的版本,可以自行用composer
来安装这个插件。
测试之后,问题解决。
参考链接
Load Blade assets with https in Laravel
Nginx反向代理Apache,并解决Laravel在反向代理情况下的HTTPS加密问题
转载说明
转载请注明出处,无偿提供。