什么是 Keycloak
Keycloak 是一个针对现代应用程序和服务的开源身份和访问管理解决方案。Keycloak 支持单点登录(Single-Sign On),因此服务可以通过 OpenID Connect、OAuth 2.0 等协议对接 Keycloak。同时 Keycloak 也支持集成不同的身份认证服务,例如 Github、Google 和 Facebook 等。
另外 Keycloak 也支持用户联邦功能,可以通过 LDAP 或 Kerberos 来导入用户。更多 Keycloak 内容可以参考官方文档介绍。
如何使用
环境准备
在进行如下步骤前,请确保环境中已启动 Apache APISIX。
启动 Keycloak
这里我们使用 docker-compose
将 Keycloak 与其所依赖的的 PostgreSQL 一并启动。
1version: '3.7'
2
3services:
4 postgres:
5 image: postgres:12.2
6 container_name: postgres
7 environment:
8 POSTGRES_DB: keycloak
9 POSTGRES_USER: keycloak
10 POSTGRES_PASSWORD: password
11
12 keycloak:
13 image: jboss/keycloak:9.0.2
14 container_name: keycloak
15 environment:
16 DB_VENDOR: POSTGRES
17 DB_ADDR: postgres
18 DB_DATABASE: keycloak
19 DB_USER: keycloak
20 DB_PASSWORD: password
21 KEYCLOAK_USER: admin
22 KEYCLOAK_PASSWORD: password
23 PROXY_ADDRESS_FORWARDING: "true"
24 ports:
25 - 8080:8080
26 depends_on:
27 - postgres
1docker-compose up
执行完毕后需要确认 Keycloak 和 PostgreSQL 是否已成功启动。
1docker-compose ps
配置 Keycloak
Keycloak 启动完成之后,使用浏览器访问 "http://127.0.0.1:8080/auth/admin/",并键入 admin/password
账号密码进行登录管理员控制台。
创建 realm
首先,创建一个名称为 apisix_test_realm
的 realm
。在 Keycloak 中,realm
是一个专门用来管理项目的工作区,不同 realm
之间的资源是相互隔离的。
Keycloak 中 realm
分为两类:一类是 master realm
,由 Keycloak 刚启动时创建,用于管理 admin 账号以及创建其他的 realm
。第二类是 other realm
,由 master realm
中的 admin 创建,可以在该 realm
中进行用户和应用的创建并进行管理和使用。更多细节可参考 Keycloak 中 realm 和 users 相关内容。
创建 Client
接下来需要创建 OpenID Connect Client
。在 Keycloak 中,Client 表示允许向 Keycloak 发起身份认证的客户端。
在本示例场景中,Apache APISIX
相当于一个客户端,负责向 Keycloak 发起身份认证请求,因此我们创建一个名称为 apisix
的 Client。关于 Client 更多细节可参考 Keycloak OIDC Clients。
配置 Client
Client 创建完成后,需要为 Client 配置 Apache APISIX 的访问类型。
在 Keycloak 中 Access Type
分为三类:
- confidential。适用于需要执行浏览器登录的应用,客户端会通过
client secret
来获取access token
, 多运用于服务端渲染的 web 系统。 - public。适用于需要执行浏览器登录的应用,多运用于使用 vue 和 react 实现的前端项目。
- bearer-only。适用于不需要执行浏览器登录的应用,只允许携带
bearer token
访问,多运用于 RESTful API 的使用场景。
更多关于 Client 设置细节可参考 Keycloak OIDC Clients 高级设置。
因为我们使用了 Apache APISIX 作为服务端的 Client, 因此可以选择类型一或类型三(这里以类型一为例进行演示)。
创建 User
Keycloak 支持对接其他第三方的用户系统,例如 Google 和 Facebook。或者使用 LDAP 的方式进行导入或手动创建用户,这里我们使用「手动创建用户」来进行演示。
在 Credentials 页面设置用户的密码。
创建路由
Keycloak 配置完成后,需要在 Apache APISIX 中创建路由并开启 Openid-Connect
插件,具体关于该插件的配置文档可以参考 Apache APISIX OpenID-Connect 插件。
获取 client_id 和 client_secret
上图配置中:
client_id
为之前创建 Client 时使用的名称,即apisix
;client_secret
则需要进入 Clients-apisix-Credentials 中获取,例如:d5c42c50-3e71-4bbe-aa9e-31083ab29da4
。
获取 discovery 配置项
进入 Realm Settings-General-Endpoints 中,选择 OpenID Endpoint Configuration
链接,复制该链接指向的地址。例如:http://127.0.0.1:8080/auth/realms/apisix_test_realm/.well-known/openid-configuration
。
创建路由并开启插件
使用如下命令访问 Apache APISIX Admin 接口来创建一条路由,设置上游为 httpbin.org
,并开启插件 OpenID Connect 用于身份认证。
注意:如果创建 Client 时,选择
bearer-only
作为Access Type
,在配置路由是需要将bearer_only
设置为 true,此时访问 Apache APISIX 将不会跳转到 Keycloak 登录界面。
1curl -XPOST 127.0.0.1:9080/apisix/admin/routes -H "X-Api-Key: edd1c9f034335f136f87ad84b625c8f1" -d '{
2 "uri":"/*",
3 "plugins":{
4 "openid-connect":{
5 "client_id":"apisix",
6 "client_secret":"d5c42c50-3e71-4bbe-aa9e-31083ab29da4",
7 "discovery":"http://127.0.0.1:8080/auth/realms/apisix_test_realm/.well-known/openid-configuration",
8 "scope":"openid profile",
9 "bearer_only":false,
10 "realm":"apisix_test_realm",
11 "introspection_endpoint_auth_method":"client_secret_post",
12 "redirect_uri":"http://127.0.0.1:9080/"
13 }
14 },
15 "upstream":{
16 "type":"roundrobin",
17 "nodes":{
18 "httpbin.org:80":1
19 }
20 }
21}'
访问测试
上述配置完成后,我们就可以在 Apache APISIX 中进行相关的测试访问了。
访问 Apache APISIX
使用浏览器访问 http://127.0.0.1:9080/image/png
。
由于开启了 OpenID-Connect 插件,并且设置了 bearer-only
为 false
。因此第一次访问该路径时, Apache APISIX 将重定向到 Keycloak 中 apisix_test_realm
中配置的登录界面,进行用户登录请求。
输入之前配置 Keycloak 时创建的 User peter,即可完成用户登录。
访问成功
登录成功后,浏览器又会将链接重定向到 "http://127.0.0.1:9080/image/png"。并成功访问到该图片内容,该内容与上游 "http://httpbin.org/image/png" 一致。
登出账号
测试完毕后,使用浏览器访问 "http:/127.0.0.1:9080/logout" 进行账号登出。
注意:登出路径可通过 OpenID-Connect 插件配置中的
logout_path
指定,默认为logout
。
总结
本文通过详细的步骤为大家展示了如何在 Apache APISIX 使用 OpenID-Connect 协议和 Keycloak 进行身份认证。通过对接 Keycloak,Apache APISIX 仅需通过配置即可实现对使用者和应用服务进行认证与鉴权,从而大大减少了相关开发工作。
更多关于 Apache APISIX 中的身份认证功能实现也可参考文章《使用 Apache APISIX 和 Okta 来实现集中式身份认证》。