GAE标准环境调用弹性环境时X-Appengine-Inbound-Appid头丢失问题
我之前在GAE跨环境调用的时候也踩过这个坑!你手动设置X-Appengine-Inbound-Appid头被移除是因为这个是GAE的保留系统头——GAE会自动为同项目内的服务间请求生成这个头,用户手动设置的会被直接覆盖或者丢弃,尤其是标准环境到弹性环境的调用场景。
下面是我当时解决这个问题的完整步骤:
1. 改用GAE内部服务域名调用
首先,MS1调用MS2时,必须使用同项目的内部服务域名,而不是外部公开域名。举个例子,如果你的项目ID是my-project-123,MS2的服务名是ms2,那么调用URL应该是:https://ms2-dot-my-project-123.appspot.com
用这个域名调用的话,GAE会自动在请求中注入两个关键头:
X-Appengine-Inbound-Appid: 值为你的项目ID(确保请求来自同项目内的服务)X-Appengine-Service: 值为发起请求的服务名(也就是ms1,用来精准限定调用来源)
你完全不需要手动设置这两个头,GAE会帮你处理好。
2. 在MS2中添加请求验证逻辑
接下来在MS2的代码里,通过过滤器或拦截器验证这两个头,确保只有MS1的请求能通过。这里给你一个Spring Boot的实现示例:
第一步:编写验证过滤器
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class GaeServiceAuthFilter implements Filter { // 替换成你的项目ID private static final String EXPECTED_APP_ID = "your-project-id"; // 替换成MS1的服务名 private static final String EXPECTED_SERVICE = "ms1"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String inboundAppId = httpRequest.getHeader("X-Appengine-Inbound-Appid"); String inboundService = httpRequest.getHeader("X-Appengine-Service"); // 验证两个头是否符合预期 if (EXPECTED_APP_ID.equals(inboundAppId) && EXPECTED_SERVICE.equals(inboundService)) { chain.doFilter(request, response); } else { httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); httpResponse.getWriter().write("Unauthorized: Only MS1 can access this API"); } } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} }
第二步:注册过滤器到Spring Boot
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<GaeServiceAuthFilter> gaeServiceAuthFilter() { FilterRegistrationBean<GaeServiceAuthFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new GaeServiceAuthFilter()); // 指定要保护的API路径,比如所有/api开头的接口 registrationBean.addUrlPatterns("/api/*"); return registrationBean; } }
3. 额外注意事项
- 你之前设置的
setInstanceFollowRedirects(false)是正确的,保持这个配置,避免重定向导致头信息丢失。 - 如果你的MS2配置了自定义VPC,需要确保MS1的标准环境能访问到VPC内的MS2(默认情况下同项目GAE服务是互通的,一般不需要额外配置)。
- 测试阶段可以在MS2的控制器中打印请求头,确认
X-Appengine-Inbound-Appid和X-Appengine-Service是否正确注入:
@GetMapping("/debug/headers") public Map<String, String> debugHeaders(HttpServletRequest request) { Map<String, String> headers = new HashMap<>(); headers.put("X-Appengine-Inbound-Appid", request.getHeader("X-Appengine-Inbound-Appid")); headers.put("X-Appengine-Service", request.getHeader("X-Appengine-Service")); return headers; }
这样就能确保MS2只接收来自MS1的合法请求了!
内容的提问来源于stack exchange,提问作者Mithun
相关产品推荐
相关产品推荐

