作为一款微服务网关应用,Kong 通过插件功能实现了微服务网关的多种功能,此处分别以访问认证、请求终止、数据整形为例,为了方便读者理解和应用,此处均使用管理接口直接操作,功能参数仍以 Konga 页面显示的名称进行说明。
Kong 提供了基本认证、密钥认证、OAuth2 认证、HMAC 认证、JWT 认证、LDAP 认证等多种方式的认证插件,此处列举常见的密钥认证方式配置。密钥认证插件参数说明如下表所示。
参数名 | 参数说明 |
---|---|
consumer | 消费者 ID,如果为空则对所有消费者有效 |
key names | 密钥名称,用户可在请求头或请求参数中使用该字段提交密钥,该值为数组,可以添加多个名称。密钥名只能包含 [a-2]1a-2][0-91[uu] 和 [-] |
hide credentials | 设置是否将密钥名称字段传递给被代理服务器,指令值为 true 时将不向被代理服务器传递该字段 |
anonymous | 如果身份验证失败,则用作 anonymous 消费者的可选字符串(消费者对象实例 uuid)值。默认值为空,表示直接返回验证失败状态码 4××。此值必须引用 Kong 内的消费者 ID 属性,而不是 "custom id" |
key in body | 如果设置为 true,Kong 插件将尝试从请求体中读取密钥名称,支持请求体的 MIME 类型有 application/www-form-urlencoded、application/json 和 multipart/form-data |
run on preflight | 如果设置为 true,该插件将在请求之前运行。否则在请求任何阶段均被允许 |
接口认证是服务开发中常见的功能,Kong 插件的认证功能可以让开发工程师不必单独开发此功能,仅需选择使用 Kong 的认证机制或通过认证转发使用内部的认证服务器,让所有的接口服务很容易地实现统一认证的功能。在下面的配置样例中,在 Konga 中按照参数配置添加密钥认证插件,认证密钥名称为 apikey。
# 创建服务
curl -i -X POST \
--url http://10.10.4.8:8001/services/ \
--data 'name=baidu' \
--data 'url=https://www.baidu.com'
# 创建路由
curl -i -X POST \
--url http://10.10.4.8:8001/services/baidu/routes \
--data 'name=baidu' \
--data 'paths[]=/v1/baidu'
# 访问测试,确认路由规则
curl -i -X GET \
--url http://10.10.4.8:8000/v1/baidu
# 关联插件到路由对象实例baidu
curl -i -X POST \
--url http://10.10.4.8:8001/routes/baidu/plugins \
--data "name=key-auth" \
--data "config.key_names=apikey" \
# 创建消费者
curl -d "username=test123" http://10.10.4.8:8001/consumers/
# 创建消费者密钥
curl -X POST http://10.10.4.8:8001/consumers/test123/key-auth -d ''
# 查看并获得密钥
curl http://10.10.4.8:8001/consumers/test123/key-auth
# 消费者使用密钥访问
curl -i -X GET \
--url http://10.10.4.8:8000 \
--header "apikey: xKgpAM6qBQE3e8nrR51dIrK89ggRdelf"
请求终止(request-termination)插件原设计场景是进行请求熔断等安全管理,但其同样适用于做依赖该接口的测试桩场景,通过 Kong 的请求终止插件可以非常快速地实现该功能,而且不需要做任何代码改动,测试桩的创建和撤销也非常简单。插件参数说明如下表所示。
参数名 | 参数说明 |
---|---|
consumer | 消费者 ID,如果为空则对所有消费者有效 |
status code | 返回响应状态码 |
content type | 相应数据 MIEM 类型 |
body | 设置响应数据内容 |
下面是一个测试桩的样例,该插件可以对当前接口的请求返回固定格式的 JSON 数据,该场景可以满足不同团队合作时在真实业务 API 代码开发完毕前,让合作方、前端及测试人员进行代码升级或测试。
# 创建服务
curl -i -X POST \
--url http://10.10.4.8:8001/services/ \
--data 'name=baidu' \
--data 'url=https://www.baidu.com'
# 创建路由
curl -i -X POST \
--url http://10.10.4.8:8001/services/baidu/routes \
--data 'name=baidu2' \
--data 'paths[]=/v2/baidu'
# 访问测试,确认路由规则
curl -i -X GET \
--url http://10.10.4.8:8000/v2/baidu
# 关联插件到路由对象实例baidu
curl -i -X POST \
--url http://10.10.4.8:8001/routes/baidu2/plugins \
--data "name=request-termination" \
--data "config.status_code=200" \
--data "config.content_type=application/json; charset=utf-8" \
--data "config.body={\"status\": 200, \"data\": {\"status_code\": 403, \"message\": \"测试数据\"}, \"message\": \"专业测试桩\"}"
# 测试结果
curl -i -X GET \
--url http://10.10.4.8:8000/v2/baidu
通常一套服务提供的 JSON 格式数据是固定的,但在多个团队的开发合作中,可能需要对接口数据返回格式有不同的需求,以往大家都希望用一个统一的标准进行规范化的 JSON 数据格式输出,但执行起来则会遇到诸多现实问题。
通过 Kong 的插件可以让使用方和供给方不必再为这种标准而纠结,开发人员不需要修改代码,仅需要简单进行 Lua 脚本编写就可以实现现有服务的供给或使用需求,这里使用 Kong 的第三方插件 API 转换(API Transformer)插件做样例在中间进行数据整形,大家也可以根据实际需求定制自己的 Kong 插件。API 转换插件功能参数如下表所示。
参数名 | 参数说明 |
---|---|
consumer | 消费者 ID,如果为空则对所有消费者有效 |
request transformer | 请求数据整形脚本路径,必选项 |
response transformer | 响应数据整形脚本路径,必选项 |
http 200 always | HTTP 响应码总为 200 |
此处演示将管理接口返回的 JSON 数据格式修改为前端 jQuery 插件 DataTables 的数据格式。因 API 转换插件的 request_transformer 参数为必选项,即便不需要请求阶段数据整形,也要为此参数指定文件,如下样例中将创建一个返回空数据的 req.lua 文件。
# 安装插件
git clone https://github.com/qnap-dev/kong-plugin-api-transformer.git
cd kong-plugin-api-transformer
luarocks make
# 启用插件,需要重启Kong才可生效
sed -i "/\"session\",/a\ \"api-transformer\"" /usr/local/share/lua/5.1/kong/constants.lua
# 创建服务,代理目标为管理接口
curl -i -X POST \
--url http://10.10.4.8:8001/services/ \
--data 'name=adminapi' \
--data 'url=http://10.10.4.8:8001'
# 创建路由
curl -i -X POST \
--url http://10.10.4.8:8001/services/adminapi/routes \
--data 'name=adminapi' \
--data 'paths[]=/adminapi'
# 访问测试,确认路由策略
curl -i -X GET \
--url http://10.10.4.8:8000/adminapi
# 关联插件到路由adminapi
curl -X POST http://10.10.4.8:8001/routes/adminapi/plugins \
--data "name=api-transformer" \
--data "config.request_transformer=/etc/kong/scripts/req.lua" \
--data "config.response_transformer=/etc/kong/scripts/datatables.lua" \
--data "config.http_200_always=true"
# 创建req.lua,此处需要在Kong系统中进行操作
mkdir -p /etc/kong/scripts
echo "return true, \"\"" > /etc/kong/scripts/req.lua
# 创建响应数据整形脚本datatables.lua,此处需要在Kong系统中进行操作
cat>/etc/kong/scripts/datatables.lua<<EOF
local return_body = {
data = {}
}
local _resp_json_body = ngx.ctx.resp_json_body
return_body.data = _resp_json_body.data
local i = 0;
for _, obj in pairs(return_body.data) do
# 此处可进行相关字段的变更或过滤
i = i + 1;
end
return_body["page_size"] = i
return_body["recordsFiltered"] = i
return_body["recordsTotal"] = i
return true, _cjson_encode_(return_body)
EOF
# 访问测试,确认返回数据
curl -i -X GET \
--url http://10.10.4.8:8000/adminapi/routes
Kong 的插件都是基于 Lua 脚本实现的,通过 Nginx 可以实现用户请求过程中各阶段的数据操作,此处不再举例,大家可以根据实际需求灵活使用 Kong 的功能。