Spring Boot微服务如何限制直接访问,仅允许通过API网关调用?
限制Owner服务直接访问的几种可行方案
1. 自定义请求头校验(推荐本地/开发环境快速验证)
让Security服务通过Feign调用Owner时,添加专属内部请求头,Owner服务校验该头的合法性,仅允许携带合法头的请求通行。
实现步骤:
- 在Security服务配置Feign拦截器,给所有调用Owner的请求添加标识头:
import feign.RequestInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FeignConfig { @Bean public RequestInterceptor internalRequestInterceptor() { return template -> { // 添加内部服务调用专属标识 template.header("X-Internal-Request", "security-service"); }; } }
- 在Owner服务添加过滤器,校验请求头:
import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import java.io.IOException; @Component public class InternalRequestFilter implements Filter { private static final String INTERNAL_HEADER = "X-Internal-Request"; private static final String VALID_VALUE = "security-service"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpReq = (HttpServletRequest) request; String headerVal = httpReq.getHeader(INTERNAL_HEADER); if (VALID_VALUE.equals(headerVal)) { chain.doFilter(request, response); } else { HttpServletResponse httpResp = (HttpServletResponse) response; httpResp.setStatus(HttpServletResponse.SC_FORBIDDEN); httpResp.getWriter().write("Direct access is not allowed"); } } }
2. IP白名单限制(适合固定IP部署的生产环境)
在Owner服务中配置IP白名单,仅允许Security服务的IP发起请求。本地环境若都是localhost,该方案效果有限,但跨机器部署时很实用。
示例(用Spring MVC拦截器实现):
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class IpWhitelistConfig implements WebMvcConfigurer { // 替换为Security服务的实际IP,生产环境可从配置文件读取 private static final List<String> ALLOWED_IPS = List.of("127.0.0.1", "192.168.1.100"); @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptor() { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String clientIp = request.getRemoteAddr(); if (ALLOWED_IPS.contains(clientIp)) { return true; } response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write("IP not permitted"); return false; } }); } }
3. Spring Security权限控制(生产环境标准方案)
给Owner服务的接口配置专属权限,仅允许携带合法服务间认证凭证的请求访问。直接访问的请求因无有效凭证被拒绝。
核心思路:
- Security服务通过Feign调用Owner时,携带服务间专属JWT令牌(或其他认证凭证)到请求头。
- Owner服务配置Spring Security,验证令牌合法性及权限:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class OwnerSecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // 仅允许拥有SERVICE_INTERNAL权限的请求访问所有接口 .anyRequest().hasAuthority("SERVICE_INTERNAL") ) // 配置JWT资源服务器(根据实际JWT实现调整) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(/* 自定义权限转换器 */))); return http.build(); } }
4. 网络层面隔离(生产环境终极方案)
- Docker部署:创建专属内部网络,Owner服务仅加入内部网络,不暴露端口到宿主机,仅Security服务能在内部网络访问它。
- Kubernetes部署:配置NetworkPolicy,仅允许Security服务的Pod访问Owner服务的端口。
- 本地环境:调整防火墙规则,禁止外部请求访问8081端口,仅允许本地Security服务进程发起的请求(比如Windows防火墙添加入站规则,拒绝所有IP访问8081,仅放行127.0.0.1的特定进程)。
内容的提问来源于stack exchange,提问作者bhavesh agrawal
相关产品推荐
相关产品推荐

