Nginx实现静态文件鉴权代理+Java示例

Nginx配置文件

127.0.0.1_8965.conf

复制代码
server {
        listen        8965;
        server_name  127.0.0.1;
		# 文件请求
		location /file/ {
			root D:/home/pmps/;
			#autoindex on;
			# 设置鉴权的请求
			auth_request /authFileValid;
            # 从URL查询参数中获取 token,并赋值给token变量
			set $token $arg_Token;
			# 从请求头Token,并赋值给token变量
			#set $token $http_Token;
			# 直接返回错误信息
			 error_page 401 = /auth-required;
		}
		location = /authFileValid {
				internal; # 只允许内部访问
				proxy_pass http://127.0.0.1:8960/system/file/auth;
				proxy_pass_request_body off;
				proxy_set_header Content-Length "";
				proxy_set_header X-Original-URI $request_uri;
				# 设置Token 的值为变量token
				proxy_set_header Token "$token";
			}
	 
			location = /auth-required {
				 return 401; # 返回 401 状态码
			}
		# 其他接口请求
        location / {
            client_max_body_size 100m;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header REMOTE-HOST $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8960/;
        }
		
}

Java鉴权代码示例

我这里用的是SaToken,token请求头名是:Token

java 复制代码
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.context.SaHolder;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Pattern;

/**
 * 系统文件相关
 */
@Tag(name = "系统文件管理", description = "系统文件相关接口")
@RestController
@RequestMapping("/system/file")
public class SysFileController extends BaseController {


    @RequestMapping("/auth")
    @ResponseBody
    @SaIgnore
    public void authFileValid(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("Token");
        if (ObjectUtil.isEmpty(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return;
        }
        LoginUserBo loginUserByToken = LoginHelper.getLoginUserByToken(token);
        if (ObjectUtil.isNull(loginUserByToken)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return;
        }
        String originalURI = request.getHeader("X-Original-URI");
        boolean b = validateURIWithWhitelist(originalURI);
        if (!b) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
        } else {
            response.setStatus(HttpStatus.OK.value());
        }
    }

    //这里越权检查,你可以自行更换其他更好的写法
    public boolean validateURIWithWhitelist(String originalURI) {
        if (originalURI == null) {
            return false;
        }
        try {
            URI uri = new URI(originalURI);
            String path = uri.getPath();
            if (path == null) {
                return false;
            }
            // 定义允许的路径模式 - 不限制文件后缀
            // 格式: /file/2025/10/96da59e0edc2a7fa2ab7959b286235e.xxx
            Pattern allowedPattern = Pattern.compile("^/file/\\d{4}/\\d{2}/[a-zA-Z0-9][a-zA-Z0-9.-]*\\.[a-zA-Z0-9]+$");
            // 验证路径格式
            if (!allowedPattern.matcher(path).matches()) {
                return false;
            }
            return !path.contains("..") && path.split("/").length >= 5;
        } catch (Exception e) {
            return false;
        }
    }
}

访问示例

  1. 文件请求:http://127.0.0.1:8965/file/2025/10/96da59e0edc2a7fa2ab7959b286235e.png?Token=你的Token
  2. 其他接口请求:http://127.0.0.1:8965/system/user/sysUserList