Nginx实现静态文件鉴权代理+Java示例
介绍
实现nginx代理文件请求,需要登录,并且有越权检查
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,其实这一步是多余的,后端在X-Original-URI里也是可以拿到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
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;
}
}
}
访问示例
- 文件请求:http://127.0.0.1:8965/file/2025/10/96da59e0edc2a7fa2ab7959b286235e.png?Token=你的Token
- 其他接口请求:http://127.0.0.1:8965/system/user/sysUserList
如果是带路径的访问
例如:http://127.0.0.1:8965/h5/file/2025/10/96da59e0edc2a7fa2ab7959b286235e.png?Token=eyJ0eXAiO
Nginx配置文件
127.0.0.1_8965.conf
server {
listen 8975;
server_name 127.0.0.1;
# 文件请求
location /h5/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;
# 去掉URL中的/h5/file前缀,直接映射到文件路径
rewrite ^/h5/file/(.*)$ /file/$1 break;
}
...省略
Java鉴权代码示例
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;
}
// 定义允许的路径模式 - 不限制文件后缀
// 格式: /h5/file/2025/10/96da59e0edc2a7fa2ab7959b286235e.xxx
Pattern allowedPattern = Pattern.compile("^/h5/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 >= 6;
} catch (Exception e) {
return false;
}
}

浙公网安备 33010602011771号