跳到主要内容
版本:3.2.16.4

设置 API 身份认证

为了安全起见,你应该只允许经过身份认证和授权的消费者访问你的 API。API7 网关提供了多种插件来启用身份认证和授权。

在服务上启用的身份认证插件就像给 API 上的锁,而消费者凭据则是解锁它们的钥匙。在 API7 网关中,你需要一个唯一的用户名和至少一个认证凭据来设置消费者。

消费者可以使用多种不同类型的认证凭据,所有认证凭据在身份认证方面都被视为平等的。

前提条件

  1. 安装 API7 企业版
  2. 在网关组上运行 API
备注

避免在同一服务/路由上配置多个身份认证插件,以防止冲突。

为 API 启用 Key Authentication

针对服务

要在服务中的所有路由上使用 Key Authentication,请在服务上启用 Key Auth 插件

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 从侧边栏选择插件,然后点击启用插件

  3. 搜索 key-auth 插件,然后点击启用

  4. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

针对单个路由

要对特定路由使用 Key Authentication,请在路由上启用 Key Auth 插件,而不是在服务上启用。

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 在已发布的服务下,从侧边栏选择路由

  3. 选择你的目标路由,例如,get-ip

  4. 插件,点击启用插件

  5. 搜索 key-auth 插件,然后点击启用

  6. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

验证 Key Authentication

按照配置 Key Authentication 凭据创建具有 Key Authentication 凭据的消费者。

然后按照以下步骤验证 Key Authentication。

  1. 发送不带 apikey 请求头的请求:
curl -i "http://127.0.0.1:9080/ip"

由于未提供密钥,你将收到一个 HTTP/1.1 401 Unauthorized 响应,其请求正文如下:

{"message":"Missing API key found in request"}
  1. apikey 请求头中发送带有错误密钥的请求:
curl -i "http://127.0.0.1:9080/ip" -H "apikey: wrongkey"

由于密钥错误,你将收到一个 HTTP/1.1 401 Unauthorized 响应,其请求正文如下:

{"message":"Invalid API key in request"}
  1. apikey 请求头中发送带有正确密钥的请求:
curl -i "http://127.0.0.1:9080/ip" -H "apikey: alice-primary-key"

使用正确的密钥发送请求,你将收到一个 HTTP/1.1 200 OK 响应。

为 API 启用Basic Authentication

针对服务

要在服务中的所有路由上使用Basic Authentication,请在服务上启用 Basic Auth 插件

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 从侧边栏选择插件,然后点击启用插件

  3. 搜索 basic-auth 插件,然后点击启用

  4. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

针对单个路由

要对特定路由使用 Basic Authentication,请在路由上启用 Basic Auth 插件,而不是在服务上启用。

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 在已发布的服务下,从侧边栏选择路由

  3. 选择你的目标路由,例如,get-ip

  4. 插件,点击启用插件

  5. 搜索 basic-auth 插件,然后点击启用

  6. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

验证 Basic Authentication

按照配置 Basic Authentication 凭据创建具有 Basic Authentication 凭据的消费者。

请按照以下步骤验证 Basic Authentication。

  1. 发送不带 Basic Authentication 凭据的请求:
curl -i "http://127.0.0.1:9080/ip"  

由于未提供凭据,你将收到一个 HTTP/1.1 401 Unauthorized 响应,其请求正文如下:

{"message":"Missing authorization in request"}
  1. 发送带有无效 Basic Authentication凭 据(用户名密码不匹配,或用户名不存在)的请求:
curl -i "http://127.0.0.1:9080/ip" -u alice:wrong-password

由于密码与任何消费者凭据都不匹配,你将收到一个 HTTP/1.1 401 Unauthorized 响应,其请求正文如下:

{"message":"Invalid user authorization"}
  1. 发送带有正确 Basic Authentication 凭据的请求:
curl -i "http://127.0.0.1:9080/ip" -u alice:alice-password 

使用正确的凭据发送请求,你将收到一个 HTTP/1.1 200 OK 响应。

为 API 启用 JWT 认证

针对服务

要在服务中的所有路由上使用 JWT 认证,请在服务上启用 JWT Auth 插件

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 从侧边栏选择插件,然后点击启用插件

  3. 搜索 jwt-auth 插件,然后点击启用

  4. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

针对单个路由

要对特定路由使用 JWT 认证,请在路由上启用 JWT Auth 插件,而不是在服务上启用。

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 在已发布的服务下,从侧边栏选择路由

  3. 选择你的目标路由,例如,get-ip

  4. 插件,点击启用插件

  5. 搜索 jwt-auth 插件,然后点击启用

  6. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

暴露 JWT 签名端点

这是在 API7 企业版中暴露 JWT 签名端点的准备步骤。如果你使用的是对称算法(例如 HS256(默认)或 HS512),其中 API7 企业版既是 JWT 签发者又是验证者,则此步骤是强制性的。如果你使用的是非对称算法(例如 RS256 或 ES256),则此步骤是可选的,因为签发者和验证者可以是不同的两方。

jwt-auth 插件会在 /apisix/plugin/jwt/sign 创建一个内部端点来签署 JWT。使用 Public API 插件 暴露该端点:

  1. 添加一个名为 jwt-auth-api 的已发布服务,以及一个名称为 jwt-auth-api 且路径为 /api7/plugin/jwt/sign 的路由。

  2. 从侧边栏选择插件,然后点击启用插件

  3. 搜索 public-api 插件,然后点击启用

  4. 在对话框中执行以下操作:

    • 将一个空配置添加到JSON 编辑器

      {
      }
    • 点击启用

验证 JWT 认证

按照配置 JWT 认证凭据创建具有 JWT 凭据的消费者。

请按照以下步骤验证 JWT 认证。

  1. 发送不带凭据的请求:
curl -i "http://127.0.0.1:9080/ip"  

由于未提供凭据,你将收到一个 HTTP/1.1 401 Unauthorized 响应,其请求正文如下:

{"message":"Missing authorization in request"}
  1. 使用消费者 JWT 凭据中的 key 获取 JWT 令牌:
jwt_token=$(curl -s "http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=john-jwt-key") && echo $jwt_token
  1. 在请求头中携带 jwt_token 向你的 API 发送请求:
curl -i "http://127.0.0.1:9080/ip" -H "Authorization: ${jwt_token}"

使用正确的凭据发送请求,你将收到一个 HTTP/1.1 200 OK 响应。

30 秒后,令牌应该会过期。使用相同的令牌发送请求以进行验证,你将收到一个 HTTP/1.1 401 Unauthorized 响应,其请求正文如下:

{"message":"failed to verify jwt"}

为 API 启用 HMAC 认证

针对服务

要在服务中的所有路由上使用 HMAC 认证,请在服务上启用 HMAC Auth 插件

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 从侧边栏选择插件,然后点击启用插件

  3. 搜索 hmac-auth 插件,然后点击启用

  4. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

针对单个路由

要对特定路由使用 HMAC 认证,请在路由上启用 HMAC Auth 插件,而不是在服务上启用。

  1. 从侧边栏选择网关组的已发布服务,然后选择要修改的服务,例如,版本为 1.0.0httpbin

  2. 在已发布的服务下,从侧边栏选择路由

  3. 选择你的目标路由,例如,get-ip

  4. 插件,点击启用插件

  5. 搜索 hmac-auth 插件,然后点击启用

  6. 在对话框中执行以下操作:

    • 将以下配置添加到JSON 编辑器

      {
      }
    • 点击启用

验证 HMAC 认证

按照配置 HMAC 认证凭据创建具有 HMAC 凭据的消费者。

请按照以下步骤验证 HMAC 认证。

  1. 生成签名

你可以使用以下 Python 代码段或你选择的其他堆栈:

hmac-sig-header-gen.py
import hmac
import hashlib
import base64
from datetime import datetime, timezone
key_id = "john-key" # 密钥 ID
secret_key = b"john-hmac-key" # 密钥
request_method = "GET" # HTTP 方法
request_path = "/headers" # 路由 URI
algorithm= "hmac-sha256" # 可以使用 allowed_algorithms 中的其他算法
# 获取 GMT 当前日期时间
# 注意:签名将在时钟偏差(默认 300 秒)后失效
# 你可以在签名失效后重新生成签名,或者增加时钟偏差以延长有效期,但建议在安全边界内
gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
# 构造签名字符串(有序)
# 日期和任何后续的自定义请求头应小写,并用单个空格字符分隔,即 `<key>:<space><value>`
# [https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12#section-2.1.6](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12#section-2.1.6)
signing_string = (
f"{key_id}\n"
f"{request_method} {request_path}\n"
f"date: {gmt_time}\n"
)

# 创建签名
signature = hmac.new(secret_key, signing_string.encode('utf-8'), hashlib.sha256).digest()
signature_base64 = base64.b64encode(signature).decode('utf-8')

# 构造请求请求头
headers = {
"Date": gmt_time,
"Authorization": (
f'Signature keyId="{key_id}",algorithm="{algorithm}",'
f'headers="@request-target date",'
f'signature="{signature_base64}"'
)
}

# 打印请求头
print(headers)

运行脚本:

python3 hmac-sig-header-gen.py
  1. 发送不带请求头的请求:
curl -i "http://127.0.0.1:9080/ip"  

由于未提供认证凭据,你将收到一个 HTTP/1.1 401 Unauthorized 响应,其请求正文如下:

{"message":"Missing authorization in request"}
  1. 使用请求头向你的 API 发送请求:
curl -X GET "http://127.0.0.1:9080/ip" \
-H "Date: Fri, 06 Sep 2024 06:41:29 GMT" \
-H 'Authorization: Signature keyId="alice-keyid",algorithm="hmac-sha256",headers="@request-target date",signature="wWfKQvPDr0wHQ4IHdluB4IzeNZcj0bGJs2wvoCOT5rM="'

因为使用了正确的凭据发送请求,你将收到一个类似于以下内容的 HTTP/1.1 200 OK 响应:

{
"headers":{
"Accept": "*/*",
"Authorization": "Signature keyId=\"john-key\",aigorithm=\'hmac-sha256\",headers=\"@reques
t-target date\", signature=\'HtQm1m8kGvnVlztZ59)XokweovFqQN04Ui6P6NfzjRr4=\'"
"Date": "Tue, 24 Sep 2024 10:28:41 GMT",
"Host": "127.0.0.1",
"User-Agent":"curl/8.7.1",
"X-Amzn-Trace-Id": "Root=1-66f29481-7355340a05778cbb21e9b25a",
"X-Consumer-Username": "John",
"X-Credential-Identifier": "4130bb4a-0fdc-461d-be8d-2bba8a1e36dc",
"X-Forwarded-Host": "127.0.0.1"
}
}

相关阅读