问题现象

在一次前后端联调中,前端通过 HTTPS 访问网关(如 https://10.0.0.1:8443/gateway/.../uploadJar)上传 JAR 包时,浏览器显示 403 Forbidden
同时,查看 Nginx 错误日志发现如下关键信息:

[crit] open() "/home/nginx/nginx_temp/client_body_temp/0000000114" failed (13: Permission denied)
[error] open() "/home/nginx/nginx_temp/html/50x.html" failed (13: Permission denied)

请求体较大(文件上传),Nginx 在尝试缓存请求内容到磁盘时,因临时目录权限不足而失败,紧接着读取错误页面 50x.html 也因同样权限问题失败,最终导致请求被中断。


排查过程

  1. 确认请求路径
    前端请求的是 POST /gateway/xxx/uploadJar,通过反向代理转发到后端服务。

  2. 检查 Nginx 配置中的鉴权规则
    配置中有基于 Host 头的白名单检查,但日志显示的 Host 在白名单范围内,排除误拦截。

  3. 分析错误日志
    发现 crit 级别的 Permission denied 错误,明确指出 Nginx worker 进程无法向 /home/nginx/nginx_temp/client_body_temp/ 写入临时文件。
    紧接着尝试读取 50x.html 错误页时也因权限问题失败,说明错误页面目录也不可访问。

  4. 确认 Nginx 安装路径
    执行 nginx -V,发现编译参数 --prefix=/home/nginx/nginx_temp。这意味着 Nginx 的默认工作目录(包括 client_body_temphtml 等)均在 /home/nginx/nginx_temp/ 下。

  5. 核实运行用户权限
    ps aux | grep nginx 显示 worker 进程以 nginx 用户运行,该用户对 /home/nginx/nginx_temp/ 目录无写权限。


问题原因

Nginx 在处理较大请求体(如文件上传)时,如果请求体大小超过 client_body_buffer_size(默认为 8KB/16KB),就会将请求体暂时写入磁盘中的临时文件。临时文件的存放位置由 client_body_temp_path 指令指定,若未显式配置,则默认为 --prefix 编译值下的 client_body_temp 目录。

本例中,Nginx 编译时指定了 --prefix=/home/nginx/nginx_temp,因此临时目录为 /home/nginx/nginx_temp/client_body_temp。但该目录的拥有者或权限并不允许 nginx 用户写入,导致请求体缓存失败,Nginx 直接返回 500 内部错误。

由于配置中未正确设置全局 root,错误页面 50x.html 也尝试从编译默认路径 /home/nginx/nginx_temp/html/ 下读取,同样遭遇权限拒绝,所以连错误页面都无法正常返回。在某些多层代理架构下,上游代理可能将此类 500 错误包装为 403,从而让前端误以为是权限问题。


解决方案

方法一:修复默认临时目录的权限(临时方案)
mkdir -p /home/nginx/nginx_temp/client_body_temp
chown -R nginx:nginx /home/nginx/nginx_temp
chmod 750 /home/nginx/nginx_temp

同时,为正确显示错误页面,在 Nginx 配置的 server 块顶部添加:

root /usr/local/nginx/html;   # 使用实际存放50x.html的路径

然后重载 Nginx:

nginx -s reload
方法二:显式指定临时目录(推荐)

nginx.confhttp 块中添加:

client_body_temp_path /var/cache/nginx/client_body_temp;

接着创建目录并授权:

mkdir -p /var/cache/nginx/client_body_temp
chown -R nginx:nginx /var/cache/nginx

同样,在 server 块中显式设置 root 以避免错误页读取问题。

重载配置后,上传接口恢复正常,不再出现 403/500 错误。


总结

该问题的本质是:Nginx 上传大文件时缓存目录权限不足,导致请求被中断,而表象可能被混淆为 403 等状态码。
解决思路非常简单:

  • 确认 Nginx 的编译参数与运行时默认路径;
  • 确保临时文件目录(client_body_temp)对于 Nginx worker 进程用户可写;
  • 显式配置 client_body_temp_path 以解耦对编译前缀的依赖;
  • 同时注意错误页面等依赖路径的权限。

这次排查也提醒我们:无论安装 Nginx 时用何种 prefix,都应在配置中使用绝对路径显式指定关键目录,避免因默认路径权限问题引发诡异错误。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐