【问题标题】:Google Cloud Endpoints + Firebase Auth: method_info is not setGoogle Cloud Endpoints + Firebase 身份验证:未设置 method_info
【发布时间】:2017-03-12 15:08:43
【问题描述】:

所以我运行的是谷歌提供的示例代码:

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 过滤器在请求中注入一些属性。

【问题讨论】:

    标签: firebase firebase-authentication google-cloud-endpoints google-cloud-endpoints-v2


    【解决方案1】:

    我花了一些时间和一些调试才意识到应该注入 method_info 的过滤器没有被触发。

    我可以通过修改 web.xml 中的映射添加以下调度程序标签来修复它:

    <filter-mapping>
        <filter-name>endpoints-api-configuration</filter-name>
        <servlet-name>EndpointsServlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    

    【讨论】:

      【解决方案2】:

      生成并部署 OpenAPI 配置文件

      $ mvn clean package endpoints-framework:openApiDocs -DskipTests
      $ gcloud endpoints services deploy target/openapi-docs/openapi.json
      $ mvn appengine:run 
      

      【讨论】:

      • 这也适用于我,虽然我仍然使用 Swagger,但对于端点团队来说,如果不依赖于开箱即用,这似乎有点短视一个外部和共享的注册表。
      【解决方案3】:

      我收到了同样的错误消息,并最终追踪到在我的 API 未指定的 URL 中使用尾随 / 发出请求。尾部斜杠只会导致提供授权令牌的调用出错。

      显然ControlFilter(因此还有GoogleAppEngineControlFilter)没有将其识别为有效端点,因此没有费心将method_info附加到请求中。但后来EndpointsServlet 认为它有效的,并试图在没有所有需要的信息的情况下进行身份验证!

      解决方法很简单:从我的请求中的 URL 中删除尾部斜杠。然而,追查问题不是!我知道这不是你的问题,但也许这个答案会对其他人有所帮助。

      【讨论】:

        【解决方案4】:

        @Kevendra 的回答强调,如果openapi.json 文件缺少对端点 API 方法的引用,则可能会导致此问题。 Firebase 可能正在使用它来引用和发现 API 方法。

        来自 Google OpenAPI 概述:

        OpenAPI 文档的基本结构:

        OpenAPI 文档描述了 REST API 的表面,并定义如下信息:

        API 的名称和描述。各个端点(路径) 在 API 中。调用者的身份验证方式。

        按照以下步骤重新生成和部署 openapi.json 文件:


        生成:

        $ mvn clean package endpoints-framework:openApiDocs -DskipTests
        
        • mvn clean - 运行一个 Maven 目标来清理你的项目。 package - 编译打包
        • endpoints-framework:openApiDocs 生成 OpenAPI 文档。这将在以下位置生成openapi.json 文件:target/openapi-docs/openapi.json - 请参阅generating and deploying an api configuration
        • -DskipTests 跳过运行任何测试,以避免由于任何测试失败 到尚未生成的 openapi.json

        部署:

        (作为预防措施,您可以先验证从以下命令返回的项目 ID,以确保服务没有在错误的项目中创建 - gcloud config list project

          $ gcloud endpoints services deploy target/openapi-docs/openapi.json
        

        从其生成的位置部署 openapi.json 文件(在上面的“生成”步骤中)。请参阅 Deploying the OpenAPI document 上的 Google 文档

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-11
          • 1970-01-01
          • 2016-02-03
          • 2017-07-06
          • 2018-12-29
          • 1970-01-01
          • 2017-08-30
          • 1970-01-01
          相关资源
          最近更新 更多