部署 Casdoor 身份认证管理系统并实现透过 OAuth2.0 登录到 WordPress
前言
由于考虑到 XCTRA 未来可能会有非常多的子服务,如果全部采用单一认证可能会非常复杂,于是这几天一直在研究 IAM(Identity and Access Management)系统,在尝试了 Apache keycloak,JustAuthPlus 等开源项目后,最终选择了 Casdoor。
Casdoor 是什么
Casdoor 是一个支持 OAuth 2.0、OIDC 和 SAML 的 UI 优先集中式身份验证/单点登录 (SSO) 平台,使用 Go 开发,前后端分离,内置第三方应用登录服务。
让我选择 Casdoor 而不是其他项目的原因是因为首先 Casdoor 是由国内开发的,对大陆网络环境支持较好,其次是 Casdoor 奉行“UI 优先”的理念,这对于我这种颜值党来说非常友好,最后,Casdoor 的安装十分简单,仅需 Go 和 NodeJS(Yarn) 环境即可运行,十分容易(由于一些原因,我的服务器没有办法使用 Docker 直接部署环境,因此必须手动部署)
Casdoor 有四个核心概念,分别是 组织(Organization)
, 用户(User)
, 应用(Application)
和 提供商(Provider)
。组织承载用户和应用,一个用户只能隶属于一个组织,但可以登录到自己组织的多个应用中;而提供商啧代表了某种身份验证方式,例如电子邮件验证、短信验证、OAuth 验证等。
部署 Casdoor
配置 Casdoor
由于上述原因,我选择了手动部署的方式部署 Casdoor 而不是使用 Docker,如果希望使用 Docker 部署的话可以直接遵循 Casdoor 文档进行:(可选) 使用 Docker 运行 | Casdoor。
要想部署 Casdoor,则至少需要以下运行环境:
- Go 1.6+
- Node.js LTS(16或14)
- Yarn 1.x
以及准备数据库以存放数据。Casdoor 当前支持 MySQL,MariaDB,PostgreSQL,SQL Server,Oracle,SQLite 3,TiDB,这是通过 Go 的 XORM 库支持的。
接下来,将 Casdoor 仓库 clone 到本地以准备开始配置:
git clone https://github.com/casdoor/casdoor
前往 ./conf/app.conf
配置数据库信息,例如对于 MySQL,使用如下的配置文件:
driverName = mysql
dataSourceName = root:123456@tcp(localhost:3306)/
dbName = casdoor
此文件也包含许多其他个性化配置,有需要的可根据文档修改。
接下来即可编译并运行 Casdoor。
编译并运行 Casdoor
若想将 Casdoor 运行在开发模式下,则分别输入以下指令以编译并运行 Casdoor 的前端和后端服务:
cd web
yarn install
yarn start
go run main.go
接下来,即可在 http://localhost:7001/
访问 Casdoor(默认的管理员用户名和密码为 admin
和 123
)。
若想将 Casdoor 运行在生产模式下,则首先输入以下指令编译前端文件:
cd web
yarn install
yarn build
然后,编译并运行 Casdoor 的后端程序:
go build
./casdoor
接下来,即可在 http://localhost:8000/
访问 Casdoor(默认的管理员用户名和密码为 admin
和 123
)。
配置反向代理
虽然Casdoor 是一个前后端分离的架构,但在生产环境中,后端程序仍然为前端文件提供静态文件服务。 因此, 您可以使用反向代理软件,如 Nginx 来代理 Casdoor 域的所有流量,并将其重定向到后端的端口。
要想使用 Nginx 反向代理 Casdoor 服务,只需在 Nginx 配置文件中添加以下服务器配置即可:
server {
listen 80;
server_name YOUR_DOMAIN_NAME;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://127.0.0.1:8000;
}
}
然后,运行以下指令以重启 Nginx 进程:
nginx -s reload
最后,访问 http://YOUR_DOMAIN_NAME
即可。
部署完成后的 Casdoor 登录和主界面如下图所示:
使用 Casdoor 透过 OAuth2.0 协议登录 WordPress
Casdoor 支持多种用户验证方式,包括手机号验证,邮箱验证,其他 OAuth 2.0(QQ,微信,Steam等)服务验证。本文中使用了邮箱验证为应用创建 Email Provider。
Casdoor 的邮箱验证不是开箱即用的,因为我们并未向 Casdoor 说明我们的邮件服务信息。为了创建我们的 Email Provider,登录 Casdoor 后台,进入"提供商"栏目,点击"添加"按钮,选择 Email
分类,按照要求配置邮件服务的 SMTP 地址和用户名密码信息即可完成配置。
OAuth2.0 的工作流程
如果您还不了解 OAuth 是什么,则其是一个开放的用户验证标准,通过一套特定流程即可让用户账号与第三方网站完成验证。
简单来说,OAuth2.0 的流程大致如下:
- 首先,用户访问 OAuth2.0 服务端定义的认证地址,并携带
client_id
(用于识别用户希望登录的站点)、redirect_uri
(用于目标站点验证)等信息:
https://<CASDOOR_HOST>/login/oauth/authorize?
client_id=CLIENT_ID&
redirect_uri=REDIRECT_URI&
response_type=code&
scope=openid&
state=STATE
用户将被指引登录他们的账户,当登录成功后,用户的请求会被重定向至以下地址,并包含 code
和 state
两个查询参数。其中 code
是校验码,可用于获得用户信息,state
值与第一步传入的 state
参数值相同,用于防止跨站攻击:
https://REDIRECT_URI?code=CODE&state=STATE
以上地址会被由 OAuth 客户端处理,并通过向:
https://<CASDOOR_HOST>/api/login/oauth/access_token
发送 POST 请求,并携带以下 body(code
即为上文获得的 code
,client_id
和 client_secret
可简单理解为 OAuth 客户端唯一的公私钥):
{
"grant_type": "authorization_code",
"client_id": ClientId,
"client_secret": ClientSecret,
"code": Code,
}
来得到以下响应:
{
"access_token": "eyJhb...",
"id_token": "eyJhb...",
"refresh_token": "eyJhb...",
"token_type": "Bearer",
"expires_in": 10080,
"scope": "openid"
}
以上响应包含的 access_token
可用于获取用户信息(可以理解为用户的密码),expires_in
标识 access_token
的到期时间,当 access_token
到期时,可使用 refresh_token
向 OAuth 2.0 服务端申请一个新的 access_token
:
https://<CASDOOR_HOST>/api/login/oauth/refresh_token
最后,可通过携带 accessToken
向 OAuth 2.0 服务端请求用户信息:
https://<CASDOOR_HOST>/api/userinfo?accessToken=<your_access_token>
创建 Email Provider
创建 OAuth2.0 应用
登录 Casdoor 后台,进入"应用"栏目,点击"添加"按钮,输入应用信息并选择应用的提供商为之前设置好的 Email Provider,然后记下生成的客户端ID和客户端密钥(即 client_id
和 client_secret
备用)。此时 Casdoor 的配置还未完成,因为我们还未指定重定向 URL。
接下来,登录 WordPress 后台,安装 miniOrange OAuth Single Sign On
插件(注意不是 Server)。这是一个 OAuth 客户端插件。
进入 miniOrange OAuth
设置,点击 Add Application
添加应用,并依次填入之前记下的 Client ID 和 Client Secret。此时你可以看到一个 Redirect / Callback URL
,将该 URL 配置好后设置到 Casdoor 应用的 "重定向 URL 一栏",即可完成 Casdoor 的应用配置。
接下来,以此设置 Authorize Endpoint
, Access Token Endpoint
, Get User Info Endpoint
为 https://<CASDOOR_HOST>/login/oauth/authorize
, https://<CASDOOR_HOST>/api/login/oauth/access_token
, https://<CASDOOR_HOST>/api/userinfo
,完成配置即可。
最后,回到 WordPress 主页,重新登录,你便可以看到使用 OAuth 登录的选项:
点击后,即可跳转到 Casdoor 界面进行登录:
完成登录后,你便可发现你已正确的登录到 WordPress 了。至此,我们的 OAuth 验证便成功工作了。
总结
除了 WordPress 以外,通过 OAuth,我们还可以让 Casdoor 支持其他服务,籍此,我们便可统一的对用户进行管理。
实例中使用了邮件验证码的方式进行登录,实际上,我们还可以通过支持QQ,微信等 OAuth 服务的方式为用户提供更多的登录选择。
miniOrange 插件虽然很好用,但是其免费版提供的功能依然太少,例如不支持自定义 Role 映射,只能创建一个应用等,限制还是蛮多的。