所以我正在运行Google提供的示例代码:
package com.neat.backend;
/**
* An endpoint class we are exposing
*/
@Api(
name = "myApi",
version = "v1",
namespace = @ApiNamespace(
ownerDomain = "backend.neat.com",
ownerName = "backend.neat.com",
packagePath = ""
),
issuers = {
@ApiIssuer(
name = "firebase",
issuer = "https://securetoken.google.com/" + PROJECT_ID,
jwksUri = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com")
})
public class MyEndpoint {
@ApiMethod(
path = "firebase_user",
httpMethod = ApiMethod.HttpMethod.GET,
authenticators = {EspAuthenticator.class},
issuerAudiences = {@ApiIssuerAudience(name = "firebase", audiences = {PROJECT_ID})}
)
public Email getUserEmailFirebase(User user) throws UnauthorizedException {
if (user == null) {
throw new UnauthorizedException("Invalid credentials");
}
Email response = new Email(user.getEmail());
return response;
}
}
我从我的Android客户端获取Firebase令牌并尝试通过以下方式将其发送到后端:
curl -H "Authorization: Bearer FIREBASE_JWT_TOKEN" \
-X GET \
http://localhost:8080/_ah/api/echo/v1/firebase_user
我在日志中看到的错误如下:
[INFO] java.lang.IllegalStateException: method_info is not set in the request
[INFO] at com.google.api.server.spi.auth.EspAuthenticator.authenticate(EspAuthenticator.java:67)
[INFO] at com.google.api.server.spi.request.Auth.authenticate(Auth.java:100)
[INFO] at com.google.api.server.spi.request.ServletRequestParamReader.getUser(ServletRequestParamReader.java:191)
[INFO] at com.google.api.server.spi.request.ServletRequestParamReader.deserializeParams(ServletRequestParamReader.java:136)
[INFO] at com.google.api.server.spi.request.RestServletRequestParamReader.read(RestServletRequestParamReader.java:123)
[INFO] at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:350)
[INFO] at com.google.api.server.spi.handlers.EndpointsMethodHandler$RestHandler.handle(EndpointsMethodHandler.java:114)
[INFO] at com.google.api.server.spi.handlers.EndpointsMethodHandler$RestHandler.handle(EndpointsMethodHandler.java:102)
[INFO] at com.google.api.server.spi.dispatcher.PathDispatcher.dispatch(PathDispatcher.java:49)
[INFO] at com.google.api.server.spi.EndpointsServlet.service(EndpointsServlet.java:71)
[INFO] at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
我已经尝试将完全相同的代码部署到App Engine,它运行良好 . 我试过调试EspAuthenticator,似乎期望Servlet过滤器在请求中注入一些属性 .
4 回答
我花了一些时间和一些调试来意识到应该注入method_info的过滤器没有被触发 .
我可以通过修改web.xml中的映射来添加以下调度程序标记来修复它:
生成并部署OpenAPI配置文件
我得到了相同的错误消息,并最终将其跟踪到在我的API未指定的URL中发出跟踪
/
的请求 . 尾部斜杠只会导致提供授权令牌的调用出错 .显然
ControlFilter
(因此也是GoogleAppEngineControlFilter
)没有将其识别为有效 endpoints ,因此不会将method_info
附加到请求中 . 但是EndpointsServlet
认为它是有效的,并尝试在没有所有必要信息的情况下进行身份验证!修复很简单:从我的请求中的URL中删除尾部斜杠 . 然而,追踪问题并非如此!我觉得这不是你的问题,但也许这个答案可以帮助别人 .
@Kevendra的回答强调,如果
openapi.json
文件缺少对 endpoints API方法的引用,则可能导致此问题 . Firebase可能正在使用它来引用和发现API方法 .来自Google OpenAPI概述:
请按照以下步骤重新生成并部署openapi.json文件:
generate:
mvn clean
- 运行Maven目标来清理项目 .package
- 编译并打包它endpoints-framework:openApiDocs生成OpenAPI文档 . 这将在以下位置生成
openapi.json
文件:target/openapi-docs/openapi.json
- 请参阅generating and deploying an api configuration .-DskipTests
跳过运行任何测试,以避免因openapi.json尚未生成而导致任何测试失败deploy:
(作为预防措施,您可以首先验证从以下命令返回的项目ID,以确保不在错误的项目中创建服务 -
gcloud config list project
)从其生成的位置部署openapi.json文件(在上面的'generate'步骤中) . 请参阅Deploying the OpenAPI document上的Google文档