Nginx非HTTPS请求触发403时自定义错误页面未显示问题求助
Nginx非HTTPS请求触发403时自定义错误页面未显示问题求助
嗨,我来帮你捋捋这个问题~
你遇到的核心问题其实是Nginx内部请求自定义错误页面时,又被你的if ($scheme != "https")条件拦截了,导致陷入循环,最终只能显示默认错误页面。
具体来说:当非HTTPS请求进来时,你的if条件触发return 403,Nginx本来要内部重定向到你的自定义错误页面/error_pages/403_forbidden.html,但这个内部请求还是在HTTP的server块里,$scheme依然是http,所以又会触发if条件再次返回403,直接打断了加载自定义页面的流程,最后只能用默认页面兜底。
给你两个可行的解决方案:
方案一:给错误页面单独配置不受拦截的location
调整你的server块配置,给自定义错误页面加一个专属的location,跳过scheme检查:
server { listen 80; server_name example.com; root "/var/www/example.com"; index "index.html"; # 先定义错误页面和对应的location error_page 403 /error_pages/403_forbidden.html; location = /error_pages/403_forbidden.html { # 允许所有请求访问这个错误页面,跳过scheme检查 allow all; # 确保root指向正确的目录,保证Nginx能找到文件 root "/var/www/example.com"; } if ($scheme != "https") { return 403; } # 你的其他配置... }
方案二:拆分HTTP和HTTPS到不同server块(更推荐)
Nginx官方其实不太推荐在server块里用if(因为有不少坑),更清晰的做法是把HTTP和HTTPS请求分开处理:
# 专门处理HTTP请求的server块,直接返回403和自定义页面 server { listen 80; server_name example.com; root "/var/www/example.com"; error_page 403 /error_pages/403_forbidden.html; location = /error_pages/403_forbidden.html { root "/var/www/example.com"; } # 所有HTTP请求直接返回403 location / { return 403; } } # 处理HTTPS请求的server块 server { listen 443 ssl; server_name example.com; root "/var/www/example.com"; index "index.html"; # 这里配置你的SSL证书信息 ssl_certificate /path/to/your/cert.pem; ssl_certificate_key /path/to/your/key.pem; # 你的其他HTTPS相关配置... }
最后还要提醒你:一定要确认/var/www/example.com/error_pages/403_forbidden.html这个文件确实存在,并且Nginx进程有读取它的权限(比如文件权限设为644,目录权限设为755),不然即使配置对了,也会显示默认页面哦~
备注:内容来源于stack exchange,提问作者Kaspar
相关产品推荐
相关产品推荐

