kong auth 认证插件使用教程
背景
如何在网关层添加认证功能?本文介绍了在以 db-less 模式运行的 kong 里开启 basic-auth 和 key-auth 这两种认证机制的流程。
Kong 运行环境搭建
使用 docker 快速搭建 db-less 环境:
-
创建
docker-compose.yml
内容如下:version: "3.8" services: kong: image: kong:2.5.1 volumes: - ./kong.yml:/kong.yml environment: - KONG_DATABASE=off - KONG_DECLARATIVE_CONFIG=/kong.yml ports: - 8000:8000
-
创建
kong.yml
内容如下:这里从 public-apis 里随便找两个免费无须认证的 api 接口做测试
_format_version: "2.1" services: - name: test-basic-auth url: https://dog-api.kinduff.com/api/facts routes: - name: basic-auth-route paths: - /dog strip_path: true - name: test-key-auth url: https://meowfacts.herokuapp.com routes: - name: key-auth-route # remind: route name should be unique paths: - /cat strip_path: true
-
docker-compose up
运行服务 -
测试:
curl http://localhost:8000/dog
正常返回接口信息curl http://localhost:8000/cat
正常返回接口信息
Auth
kong 的插件可以配置在全局(对所有的 route 都会生效),或是配在某个 service(对该 service 下的 route 生效),或是配在某个 route,本文会分别配置在两个 service 下。
kong 的 auth 插件需要先定义 consumer
(可理解为 user
),然后给 consumer
添加相关认证凭据(credentials)从而实现 auth 功能。
basic-auth
下面我们给 test-basic-auth
这个 service 添加 basic-auth:
# ↓↓↓↓↓↓↓ new ↓↓↓↓↓↓↓
# 定义一个用户/consumer/user entity
consumers:
- username: dog-user
# 使用 basic-auth 需要定义 basicauth_credentials entity
basicauth_credentials:
- consumer: dog-user # 指定该 credential 属于哪个用户
username: dog # basic auth username
password: dog-pwd # basic auth password
# ↑↑↑↑↑↑↑ new ↑↑↑↑↑↑↑
services:
- name: test-basic-auth
# ↓↓↓↓↓↓↓ new ↓↓↓↓↓↓↓
plugins:
# 在该 service 下启用该插件,这里无须指定 consumer,basic-auth 插件会基于请求头的信息找到与之匹配的 credential
- name: basic-auth
# ↑↑↑↑↑↑↑ new ↑↑↑↑↑↑↑
因为 basic-auth 插件是 kong 自带并默认启用的,我们无须手动激活它,
重新运行 docker-compose up
,然后测试:
curl http://localhost:8000/dog
返回了401 { "message":"Unauthorized" }
curl http://dog:dog-pwd@localhost:8000/dog
返回接口数据curl http://dog:wrong-pwd@localhost:8000/dog
返回了{ "message":"Invalid authentication credentials" }
key-auth
key-auth 的启用和上述 basic-auth 思路是一样的,只是两者的认证方式不同,故 credential 的配置会不一样:
_format_version: "2.1"
consumers:
# ↓↓↓↓↓↓↓ new ↓↓↓↓↓↓↓
- username: cat-user
# ↑↑↑↑↑↑↑ new ↑↑↑↑↑↑↑
keyauth_credentials:
# ↓↓↓↓↓↓↓ new ↓↓↓↓↓↓↓
- consumer: cat-user
key: random-key
# ↑↑↑↑↑↑↑ new ↑↑↑↑↑↑↑
services:
- name: test-key-auth
# ↓↓↓↓↓↓↓ new ↓↓↓↓↓↓↓
plugins:
- name: key-auth
# ↑↑↑↑↑↑↑ new ↑↑↑↑↑↑↑
key-auth 插件支持设置 key 的读取位置,默认是从请求头里读取 apiKey
,大家实际使用时可根据文档自行配置修改,比如需要从请求体里读取,或是名字换成 token
而不是 apiKey
,本文将使用默认配置
key-auth 插件也是 kong 自带并默认启用的,我们无须手动激活它,
重新运行 docker-compose up
,然后测试:
curl http://localhost:8000/cat
返回了401 { "message":"No API key found in request" }
curl -H 'apiKey:random-key' http://localhost:8000/cat
返回接口数据curl -H 'apiKey:wrong-random-key' http://localhost:8000/cat
返回了{ "message":"Invalid authentication credentials" }
一些注意事项(采坑)
-
请确保自己可以区分请求的响应内容是否是由上游服务返回的,以便在排查问题时瞄准问题是出在 kong 还是上游服务:默认 kong 会在响应头里包含多个特殊头,其中
X-Kong-Upstream-Status
头会附加上游服务的响应码 ,如果请求没有走到上游,则该响应头不会存在,以此我们便可以确定服务问题出在了哪里。 -
上述的 auth 插件里都有个
hide_credentials
的配置,默认是false
,表示在将请求转发到上游服务器前,不会移除Authorization
、apiKey
等请求头,如果你的上游服务也有一套自己的认证逻辑,比如也是基于Authorization
认证,则会和网关层配置的认证产生冲突,但如果设置为true
将其隐藏,则上游服务拿不到Authorization
头,也会存在问题。所以在涉及认证逻辑时,需要认真思考认证服务的设计,要么认证统一交由网关层处理,要么是转发到专门的认证服务,避免"双管齐下"。