设置 API 认证
为了安全起见,你应该只允许经过认证和授权的消费者(consumers)访问你的 API。API7 网关提供了多种插件来实现认证和授权。
在服务(services)上启用的认证插件充当了 API 的锁,而消费者的凭证则作为解锁的钥匙。在 API7 网关中,你需要一个唯一的用户名和至少一个凭证来设置消费者。
消费者可以使用不同类型的多个凭证,并且在认证时它们被同等对待。
先决条件
避免在同一服务/路由上配置多个认证插件,以防发生冲突。
为 API 启用 key-auth 认证
为服务启用
如果要对服务中的所有路由使用 key-auth 认证,请在服务上启用 Key Auth 插件。
- Dashboard
- ADC
- Ingress Controller
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 从侧边导航栏中选择插件,然后点击新增插件。
- 搜索
key-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新服务配置以使用 key-auth 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
plugins:
key-auth:
_meta:
disable: false
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
将配置同步到 API7 企业版:
adc sync -f adc-consumer.yaml -f adc-service.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
为路由(同时也会创建一个服务)创建一个启用了 key-auth 认证的 Kubernetes 清单文件:
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: api7
name: auth-plugin-config
spec:
plugins:
- name: key-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: api7
name: httpbin
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /ip
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: auth-plugin-config
backendRefs:
- name: httpbin
port: 80
将配置应用到你的集群:
kubectl apply -f httpbin-key-auth.yaml
APISIX CRD 目前不支持在服务级别启用插件。
为单个路由启用
- Dashboard
- ADC
- Ingress Controller
如果要对特定路由使用 key-auth 认证,请在路 由上而不是服务上启用 Key Auth 插件。
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 在服务下,从侧边导航栏选择路由。
- 选择目标路由,例如
get-ip。 - 在插件字段中,点击新增插件。
- 搜索
key-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新路由配置以使用 key-auth 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
plugins:
key-auth:
_meta:
disable: false
将配置同步到 API7 网关:
adc sync -f adc-consumer.yaml -f adc-route.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
Gateway API 目前不支持在路由级别启用插件。
为路由(同时也会创建一个服务)创建一个启用了 key-auth 认证的 Kubernetes 清单文件:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: api7
name: httpbin
spec:
ingressClassName: apisix
http:
- name: get-ip
match:
paths:
- /ip
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: key-auth
enable: true
将配置应用到你的集群:
kubectl apply -f httpbin-key-auth.yaml
验证 key-auth 认证
按照配置 key-auth 认证凭证创建一个带有 key-auth 认证凭证的消费者。
然后按照以下步骤验证 key-auth 认证。
- 发送不带
apikey请求头的请求:
curl -i "http://127.0.0.1:9080/ip"
由于未提供 key,你将收到一个带有以下响应体的 HTTP/1.1 401 Unauthorized 响应:
{"message":"Missing API key found in request"}
- 发送在
apikey请求头中包含错误 key 的请求:
curl -i "http://127.0.0.1:9080/ip" -H "apikey: wrongkey"
由于 key 错误,你将收到一个带有以下响应体的 HTTP/1.1 401 Unauthorized 响应:
{"message":"Invalid API key in request"}
- 发送在
apikey请求头中包含正确 key 的请求:
curl -i "http://127.0.0.1:9080/ip" -H "apikey: alice-primary-key"
当请求中包含正确的 key 时,你将收到一个 HTTP/1.1 200 OK 响应。
为 API 启用 basic-auth 认证
为服务启用
如果要对服务中的所有路由使用 basic-auth 认证,请在服务上启用 Basic Auth 插件。
- Dashboard
- ADC
- Ingress Controller
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 从侧边导航栏中选择插件,然后点击新增插件。
- 搜索
basic-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新服务配置以使用 basic-auth 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
plugins:
basic-auth:
_meta:
disable: false
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
将配置同步到 API7 企业版:
adc sync -f adc-consumer.yaml -f adc-service.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
为路由(同时也会创建一个服务)创建一个 Kubernetes 清单文件,并在服务级别启用了 basic-auth 认证:
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: api7
name: auth-plugin-config
spec:
plugins:
- name: basic-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: api7
name: httpbin
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /ip
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: auth-plugin-config
backendRefs:
- name: httpbin
port: 80
将配置应用到你的集群:
kubectl apply -f httpbin-basic-auth.yaml
APISIX CRD 目前不支持在服务级别启用插 件。
为单个路由启用
- Dashboard
- ADC
- Ingress Controller
如果要对特定路由使用 basic-auth 认证,请在路由上而不是服务上启用 Basic Auth 插件。
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 在服务下,从侧边导航栏选择路由。
- 选择目标路由,例如
get-ip。 - 在插件字段中,点击新增插件。
- 搜索
basic-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新路由配置以使用 basic-auth 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
plugins:
basic-auth:
_meta:
disable: false
将配置同步到 API7 网关:
adc sync -f adc-consumer.yaml -f adc-route.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
Gateway API 目前不支持在路由级别启用插件。
为路由(同时也会创建一个服务)创建一个启用了 basic-auth 认证的 Kubernetes 清单文件:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: api7
name: httpbin
spec:
ingressClassName: apisix
http:
- name: get-ip
match:
paths:
- /ip
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: basic-auth
enable: true
将配置应用到你的集群:
kubectl apply -f httpbin-basic-auth.yaml
验证 basic-auth 认证
按照配置 basic-auth 认证凭证创建一个带有 basic-auth 认证凭证的消费者。
按照以下步骤验证 basic-auth 认证。
- 发送不带 basic-auth 认证凭证请求头的请求:
curl -i "http://127.0.0.1:9080/ip"
由于未提供凭证,你将收到一个带有以下响应体的 HTTP/1.1 401 Unauthorized 响应:
{"message":"Missing authorization in request"}
- 发送带有无效 basic-auth 认证凭证(用户名和密码不匹配,或用户名不存在)请求头的请求:
curl -i "http://127.0.0.1:9080/ip" -u alice:wrong-password
由于密码与任何消费者凭证都不匹配,你将收到一个带有以下响应体的 HTTP/1.1 401 Unauthorized 响应:
{"message":"Invalid user authorization"}
- 发送带有正确 basic-auth 认证凭证的请求:
curl -i "http://127.0.0.1:9080/ip" -u alice:alice-password
当请求中包含正确的凭证时,你将收到一个 HTTP/1.1 200 OK 响应。
为 API 启用 JWT 认证
为服务启用
如果要对服务中的所有路由使用 JWT 认证,请在服务上启用 JWT Auth 插件。
- Dashboard
- ADC
- Ingress Controller
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 从侧边导航栏中选择插件,然后点击新增插件。
- 搜索
jwt-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新服务配置以使用 JWT 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
plugins:
jwt-auth:
_meta:
disable: false
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
将配置同步到 API7 企业版:
adc sync -f adc-consumer.yaml -f adc-service.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
为路由(同时也会创建一个服务)创建一个 Kubernetes 清单文件,并在服务级别启用了 JWT 认证:
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: api7
name: auth-plugin-config
spec:
plugins:
- name: jwt-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: api7
name: httpbin
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /ip
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: auth-plugin-config
backendRefs:
- name: httpbin
port: 80
将配置应用到你的集群:
kubectl apply -f httpbin-jwt-auth.yaml
APISIX CRD 目前不支持在服务级别启用插件。
为单个路由启用
- Dashboard
- ADC
- Ingress Controller
如果要对特定路由使用 JWT 认证,请在路由上而不是服务上启用 JWT Auth 插件。
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 在服务下,从侧边导航栏选择路由。
- 选择目标路由,例如
get-ip。 - 在插件字段中,点击新增插件。
- 搜索
jwt-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新路由配置以使用 JWT 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
plugins:
jwt-auth:
_meta:
disable: false
将配置同步到 API7 网关:
adc sync -f adc-consumer.yaml -f adc-route.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
Gateway API 目前不支持在路由级别启用插件。
为路由(同时也会创建一个服务)创建一个启用了 JWT 认证的 Kubernetes 清单文件:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: api7
name: httpbin
spec:
ingressClassName: apisix
http:
- name: get-ip
match:
paths:
- /ip
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: jwt-auth
enable: true
将配置应用到你的集群:
kubectl apply -f httpbin-jwt-auth.yaml
暴露 JWT 签名端点
这是在 API7 企业版中暴露 JWT 签名端点的准备步骤。如果你使用对称算法(如 HS256(默认)或 HS512),其中 API7 企业版将同时作为 JWT 的签发者(issuer)和验证者(validator),则此步骤是必须的。如果你使用非对称算法(如 RS256 或 ES256),则此步骤是可选的,因为签发者和验证者可以是不同的主体。
jwt-auth 插件会创建一个内部端点 /apisix/plugin/jwt/sign 来签署 JWT。使用 Public API 插件 暴露该端点:
- 添加一个名为
jwt-auth-api的服务,以及一个名为jwt-auth-api、路径为/api7/plugin/jwt/sign的路由。 - 从侧边导航栏中选择插件,然后点击新增插件。
- 搜索
public-api插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加空配置:
{
} -
点击新增。
验证 JWT 认证
按照配置 JWT 认证凭证创建一个带有 JWT 凭证的消费者。
按照以下步骤验证 JWT 认证。
- 发送不带凭证的请求:
curl -i "http://127.0.0.1:9080/ip"
由于未提供凭证,你将收到一个带有以下响应体的 HTTP/1.1 401 Unauthorized 响应:
{"message":"Missing authorization in request"}
- 使用消费者 JWT 凭证中的
key获取 JWT token:
jwt_token=$(curl -s "http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=john-jwt-key") && echo $jwt_token
- 发送在请求头中包含
jwt_token的请求到你的 API:
curl -i "http://127.0.0.1:9080/ip" -H "Authorization: ${jwt_token}"
当请求中包含正确的凭证时,你将收到一个 HTTP/1.1 200 OK 响应。
30 秒后,该 token 将会过期。发送包 含相同 token 的请求进行验证,你将收到一个带有以下响应体的 HTTP/1.1 401 Unauthorized 响应:
{"message":"failed to verify jwt"}
为 API 启用 HMAC 认证
为服务启用
如果要对服务中的所有路由使用 HMAC 认证,请在服务上启用 HMAC Auth 插件。
- Dashboard
- ADC
- Ingress Controller
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 从侧边导航栏中选择插件,然后点击新增插件。
- 搜索
hmac-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新服务配置以使用 HMAC 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
plugins:
hmac-auth:
_meta:
disable: false
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
将配置同步到 API7 企业版:
adc sync -f adc-consumer.yaml -f adc-service.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
为路由(同时也会创建一个服务)创建一个 Kubernetes 清单文件,并在服务级别启用了 HMAC 认证:
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: api7
name: auth-plugin-config
spec:
plugins:
- name: hmac-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: api7
name: httpbin
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /ip
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: auth-plugin-config
backendRefs:
- name: httpbin
port: 80
将配置应用到你的集群:
kubectl apply -f httpbin-hmac-auth.yaml
APISIX CRD 目前不支持在服务级别启用插件。
为单个路由启用
- Dashboard
- ADC
- Ingress Controller
如果要对特定路由使用 HMAC 认证,请在路由上而不是服务上启用 HMAC Auth 插件。
- 从侧边导航栏中选择你网关组的服务,然后选择你想要修改的服务,例如
httpbin。 - 在服务下,从侧边导航栏选择路由。
- 选择目标路由,例如
get-ip。 - 在插件字段中,点击新增插件。
- 搜索
hmac-auth插件,然后点击新增。 - 在对话框中执行以下操作:
-
在 JSON 编辑器 中添加以下配置:
{
} -
点击新增。
更新路由配置以使用 HMAC 认证:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
plugins:
hmac-auth:
_meta:
disable: false
将配置同步到 API7 网关:
adc sync -f adc-consumer.yaml -f adc-route.yaml
ADC 使用配置文件作为单一真实来源。因此,请确保将消费者和服务的配置文件同时传递给 adc sync 命令,以便两种配置都能生效。
- Gateway API
- APISIX CRD
Gateway API 目前不支持在路由级别启用插件。
为路由(同时也会创建一个服务)创建一个启用了 HMAC 认证的 Kubernetes 清单文件:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: api7
name: httpbin
spec:
ingressClassName: apisix
http:
- name: get-ip
match:
paths:
- /ip
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: hmac-auth
enable: true
将配置应用到你的集群:
kubectl apply -f httpbin-hmac-auth.yaml
验证 HMAC 认证
按照配置 HMAC 认证凭证创建一个带有 HMAC 凭证的消费者。
按照以下步骤验证 HMAC 认证。
- 生成签名
你可以使用下面的 Python 片段或你选择的其他技术栈:
import hmac
import hashlib
import base64
from datetime import datetime, timezone
key_id = "john-key" # 密钥 ID (key id)
secret_key = b"john-hmac-key" # 密钥 (secret key)
request_method = "GET" # HTTP 方法 (HTTP method)
request_path = "/headers" # 路由 URI (route URI)
algorithm= "hmac-sha256" # 可以使用 allowed_algorithms 中的其他算法
# 获取当前 GMT 时间
# 注意:该签名将在时钟偏移(默认 300s)后失效
# 你可以在其失效后重新生成签名,或者增加时钟偏移以在建议的安全边界内延长有效期
gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT')
# 构造签名字符串(有序的)
# date 以及任何随后的自定义请求头都应转为小写,并用单个空格字符分隔,即 `<key>:<space><value>`
# 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
- 发送不带请求头的请求:
curl -i "http://127.0.0.1:9080/ip"
由于未提供凭证,你将收到一个带有以下响应体的 HTTP/1.1 401 Unauthorized 响应:
{"message":"Missing authorization in request"}
- 发送带有请求头的请求到你的 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"
}
}