如何结合Nginx与SpringBoot API实现资源访问权限控制?
解决方案
一、Nginx 剩余配置
添加一个location块,匹配/img/下所有未被/img/public/匹配的请求,将其转发到SpringBoot服务(假设SpringBoot运行在8080端口),由SpringBoot处理权限校验:
# Handle private image requests (forward to SpringBoot for authentication) location ^~ /img/ { proxy_pass http://localhost:8080; # 转发到SpringBoot服务端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 传递原始请求URI,方便SpringBoot转发到资源服务器 proxy_set_header X-Original-URI $request_uri; }
注意:Nginx的
location匹配有优先级,/img/public/的前缀匹配优先级高于/img/,因此公共图片请求会被优先处理,不会进入SpringBoot鉴权流程。
二、SpringBoot API 实现
1. 依赖准备
确保项目中引入spring-boot-starter-web和spring-boot-starter-webclient(或spring-boot-starter-web-services用于RestTemplate):
<!-- pom.xml 示例 --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webclient</artifactId> </dependency> </dependencies>
2. Token 校验拦截器
编写拦截器统一处理Token校验逻辑,避免在Controller中重复代码:
import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ImageAuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { // 从请求头或URL参数获取Token String token = extractToken(request); // 校验Token有效性(替换为你的实际校验逻辑:比如JWT解析、数据库查询等) if (!isTokenValid(token)) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().write("Unauthorized: Invalid or missing token"); return false; } return true; } private String extractToken(HttpServletRequest request) { // 优先从Authorization头获取Bearer Token String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { return authHeader.substring(7); } // 其次从URL参数获取token return request.getParameter("token"); } // 替换为你的实际Token校验逻辑 private boolean isTokenValid(String token) { if (token == null) return false; // 示例:校验Token是否为有效JWT,或是否在缓存/数据库中存在 return "your-valid-token-check-logic".equals(token); } }
3. 注册拦截器
配置WebMvc,将拦截器绑定到/img/**路径:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new ImageAuthInterceptor()) .addPathPatterns("/img/**"); } }
4. 图片代理Controller
Token校验通过后,将请求转发到9631端口的资源服务器,返回图片内容:
import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; @RestController public class ImageProxyController { private final RestTemplate restTemplate = new RestTemplate(); // 资源服务器地址 private static final String RESOURCE_SERVER = "http://localhost:9631"; @GetMapping("/img/**") public ResponseEntity<byte[]> proxyImage(HttpServletRequest request) { // 获取原始请求URI,拼接资源服务器地址 String originalUri = request.getRequestURI(); String resourceUrl = RESOURCE_SERVER + originalUri; // 转发请求并返回响应 return restTemplate.getForEntity(resourceUrl, byte[].class); } }
内容的提问来源于stack exchange,提问作者accbear
相关产品推荐
相关产品推荐

