使用 API 密钥限制 API 访问权限

您可以使用 API 密钥来限制对 API 中的特定 API 方法或所有方法的访问。本页面介绍了如何设置限制以只允许拥有 API 密钥的客户端访问 API,同时还演示了如何创建 API 密钥。

Extensible Service Proxy (ESP) 使用 Service Control API 来验证 API 密钥及其与项目中已启用的 API 之间的关联。如果您在 API 中设置了 API 密钥要求,则对受保护的方法、类或 API 的请求将被拒绝,除非这些请求具有在您的项目或其他项目(属于已获授权可启用您的 API 的开发者)中生成的密钥。系统不会记录创建 API 密钥时所用的项目,也不会将该项目添加到请求标头中。不过,您可以按照针对特定使用方项目进行过滤中的说明,在 Endpoints > 服务页面上查看与客户端关联的 Google Cloud 项目。

如需了解应在哪个 Google Cloud 项目中创建 API 密钥,请参阅共享受 API 密钥保护的 API

限制对所有 API 方法的访问

若想要求必须具备 API 密钥才能访问 API 的所有方法,请执行以下操作:

  1. 在文本编辑器中打开项目的 openapi.yaml 文件。

  2. securityDefinitions: 下,添加 api_key:apiKeykeyquery,如以下示例代码段所示:

    securityDefinitions:
      # This section configures basic authentication with an API key.
      api_key:
        type: "apiKey"
        name: "key"
        in: "query"

    这将建立一个名为 api_key 的“安全机制”,您可用它来保护 API。如需了解其他 api_key 定义选项,请参阅 API 密钥定义限制

  3. 在文件顶层(不缩进或嵌套),将 api_key: [] 添加到 security 指令。您可能需要添加 security 指令,该指令也可能已经存在:

      security:
        - api_key: []
    

    该指令会将 api_key 安全机制应用于文件中的所有方法。请不要在方括号内添加任何内容。OpenAPI 规范要求不使用 OAuth 的安全机制必须使用空列表。

限制对特定 API 方法的访问权限

若想要求必须具备 API 密钥才能访问特定方法,请执行以下操作:

  1. 在文本编辑器中打开项目的 openapi.yaml 文件。

  2. 在文件顶层(不缩进或嵌套),添加一个空的安全指令,将其应用于整个 API:

    security: []
    
  3. securityDefinitions: 下,添加 api_key:apiKeykeyquery,如以下示例代码段所示:

    securityDefinitions:
      # This section configures basic authentication with an API key.
      api_key:
        type: "apiKey"
        name: "key"
        in: "query"

    这将建立一个名为 api_key 的“安全机制”,您可用它来保护 API。如需了解其他 api_key 定义选项,请参阅 API 密钥定义限制

  4. 在方法的定义中,将 api_key: [] 添加到 security 指令:

    ...
    paths:
      "/echo":
    post:
      description: "Echo back a given message."
      operationId: "echo"
      security:
      - api_key: []
      produces:
      ...
    

    该指令会将 api_key 安全机制应用于相应方法。请不要在方括号内添加任何内容。OpenAPI 规范要求不使用 OAuth 的安全机制必须使用空列表。

移除对某个方法的 API 密钥限制

如需为特定方法停用 API 密钥验证(即使您已限制对该 API 的访问权限),请执行以下操作:

  1. 在文本编辑器中打开项目的 openapi.yaml 文件。

  2. 在方法的定义中,添加空的 security 指令:

    ...
    paths:
      "/echo":
    post:
      description: "Echo back a given message."
      operationId: "echo"
      security: []
      produces:
      ...
    

使用 API 密钥调用 API

如以下 curl 示例所示,如果 API 或 API 方法需要 API 密钥,请使用名为 key 的查询参数提供该密钥:

 curl "${ENDPOINTS_HOST}/echo?key=${ENDPOINTS_KEY}"

其中 ENDPOINTS_HOSTENDPOINTS_KEY 分别是包含 API 主机名和 API 密钥的环境变量。

共享受 API 密钥保护的 API

API 密钥与其创建时所在的 Google Cloud 项目相关联。如果您已决定访问您的 API 需要提供 API 密钥,请回答以下几个问题,以便确定从中创建 API 密钥的 GCP 项目:

  • 您是否需要区分 API 的调用者以便使用 Endpoints 的quotas等功能?
  • API 的所有调用者是否都有自己的 Google Cloud 项目?
  • 您是否需要设置不同的 API 密钥限制

在确定从中创建 API 密钥的 Google Cloud 项目时,您可以下面的决策树为指导。

API 密钥决策树

授予启用 API 的权限

如果您需要区分 API 的各个调用者,并且每个调用者都有自己的 Google Cloud 项目,您可以向主账号授予在其自己的 Google Cloud 项目中启用 API 的权限。这样,您的 API 用户就可以创建自己的 API 密钥,以用于您的 API。

例如,假设您的团队创建了一个 API,供公司内部的各种客户端程序使用,并且每个客户端程序都有各自的 Google Cloud 项目。如需区分您的 API 的各调用者,您必须在不同的 Google Cloud 项目中为每个调用者创建 API 密钥。您可以向同事授予在与相应客户端程序关联的 Google Cloud 项目中启用 API 的权限。

要允许用户创建自己的 API 密钥,请执行以下操作:

  1. 在配置 API 的 Google Cloud 项目中,向每个用户授予启用 API 的权限
  2. 与这些用户联系,告知他们可以在其自己的 Google Cloud 项目中启用您的 API 以及创建 API 密钥

为每个调用者单独创建一个 Google Cloud 项目。

如果您需要区分 API 的调用者,但并非所有调用者都有 Google Cloud 项目,您可以为每个调用者单独创建一个 Google Cloud 项目和 API 密钥。在创建项目之前,请考虑好项目名称,以便轻松识别与该项目关联的调用者。

例如,假设您的 API 有外部客户,并且您不知道调用您的 API 的客户端程序是如何创建的。也许有些客户端会使用 Google Cloud 服务并且拥有 Google Cloud 项目,而有些客户端则可能并非如此。如需区分调用者,您必须为每个调用者单独创建一个 Google Cloud 项目和 API 密钥。

如需为每个调用者单独创建一个 Google Cloud 项目和 API 密钥,请执行以下操作:

  1. 为每个调用者单独创建一个项目。
  2. 在每个项目中,启用您的 API创建 API 密钥
  3. 将此 API 密钥提供给对应的调用者。

为每个调用者创建一个 API 密钥

如果您不需要区分 API 的调用者,但想要添加 API 密钥限制,则可以为同一项目中的每个调用者单独创建一个 API 密钥。

要为同一项目中的每个调用者创建一个 API 密钥,请执行以下操作:

  1. 在配置了您的 API 的项目中或在启用了您的 API 的项目中,为需要遵循您所需的 API 密钥限制的每位客户创建一个 API 密钥。
  2. 将此 API 密钥提供给对应的调用者。

为所有调用者创建一个 API 密钥

如果您不需要区分 API 的调用者,也不需要添加 API 限制,但仍想施加 API 密钥要求(例如,用于阻止匿名访问),则可以创建一个 API 密钥供所有调用者使用。

要为所有调用者创建一个 API 密钥,请执行以下操作:
  1. 在配置了您的 API 的项目中或在启用了您的 API 的项目中,为所有调用者创建一个 API 密钥。
  2. 将该 API 密钥提供给每个调用者。

最佳做法

如果您依赖 API 密钥来保护对 API 和用户数据的访问权限,请确保在配置 Extensible Service Proxy V2 (ESPv2) 启动选项时将 --service_control_network_fail_open 标志设置为 close。该标志的默认值为 open.

ESPv2 调用 Service Control 来验证 API 密钥。如果在连接到 Service Control 时出现网络故障并且 ESPv2 无法验证 API 密钥,这可确保使用欺诈性密钥向您的 API 发出的任何潜在请求被拒绝。

后续步骤