使用Casdoor搭建用户身份管理平台
May 30, 2024
- 开发成本
- 支持国内的QQ、Wechat等Provider
- 价格:Clerk的免费版功能限制挺多的,比如仅允许3个Provider,而现在还没有付费版的诉求。Pro版价格是$25,已经超过我腾讯云机器的价格了。
- 开源:个人偏好,不要绑定在某一个特定平台。
Casdoor的搭建流程并不复杂,后端使用GO实现,理论上资源消耗应该也不大,遂决定在我的vps上安装。
介绍
Casdoor是一个开源的身份和访问管理(IAM)/单点登录(SSO)平台。其主要特性包括:
- 前后端分离的架构,前端使用react,后端使用 Go 语言开发,Casdoor 支持高并发,提供基于Web的用户管理 UI,并支持中、英等多种语言
- Casdoor 支持 Github, Google, QQ, WeChat, Facebook, Gitee 等第三方应用程序登录,并支持使用插件扩展第三方登录
- 使用 Casbin 基于授权管理,Casdoor 支持 ACL, RBAC, ABAC, RESTful 等访问控制模型
- 个性化的注册、登录和忘记密码页面。支持手机验证码、邮件验证码、找回密码等功能
- 使用阿里云、腾讯云、七牛云提供的图片CDN云存储
- Casdoor 支持使用 db 同步方法与现有系统的集成,用户可以顺利过渡到Casdoor
- Casdoor 支持的主流数据库: MySQL, SQL Server, PostgreSQL 等, 并支持扩展插件的新数据库
安装
官方提供了多种安装方式,包括docker安装、本地服务端安装等,参考官方文档。
我采用的是本地server安装的方式,大致流程:
- git clone 后编译前端web。
- 编译后端go sever。此时已经已经将前后端打包成一个可执行文件了。
- 创建mysql database。
- 修改 conf/app.conf 配置文件中的DB配置
- 使用pm2启动服务。
- 配置Nginx、分配单独的子域名以及SSL证书。
注意点:
- 不支持path:所以需要有独立域名。我使用的自己域名下的独立子域名。后续的SMTP也使用此域名。
- 编译前端react时内存消耗较大,我的4G的vps竟然有点吃力。看官方文档应该需要2G左右,禁用sourcemap后才编译通过。
配置
使用前登录管理台,做了一些简单的配置。
基础配置
- 安全措施:修改管理员默认秘钥,禁止默认app注册。
- 新增orgnization、application,供个人博客使用。
- 注册了github provider。
- application中去掉了一些不必要的信息,比如手机号,简化注册流程。
- 登录页样式做了一些简单的调整。
SMTP
为了提供注册能力,需要提供一个可用的EMail Provier,用于验证邮箱以及找回密码登。对比一下官方文章中的几种Email Provider。
sendgrid
- 免费版:免费额度 100次/天。
- Essentials版:$20/月。
Azure
- 按使用量
brevo
- 免费版:免费额度300次/天
- Starter:5000/月
- 注册有地区限制
尝试一圈后放弃,注册流程太麻烦了,国内手机没法使用。最终看了腾讯云的SMTP服务并不贵,于是按照文档安装完毕。
其他
增加了部分Provider,比如GIT,用于支持第三方账号的直接登录。后续再慢慢增加其他类型。
使用
按照官方的列子,Next项目使用相关的改动点,包括以下部分:
- 增加认证拦截中间件:未认证用户拦截跳转到登录页page。
- 增加登录page:这里的登录页面不需要我们实现,直接跳转到casdoor的页面即可。可以理解为casdoor帮助我们完成了认证(登录)、注册的能力,然后将认证成功的用户信息(code)通过指定的redirec参数t地址返回给到我们。
上面的client、orgnization、app等需要在casdoor上面自行提前分配好。
- 用户在casdoor页面上完成注册、认证之后,casdoor会将认证 code 通过redirect的方式给到应用(即上面的redirectPath)。应用需要将code换取为 access_token ,并通过access_token获取用户详细信息,存放到cookie中。
获取到的票据包括以下字段
上面只是演示了OIDC基础使用流程,使用了session cookie来存储,如果需要持久化存储,还有一些关于票据安全的优化点需要考虑。
票据安全
cookie有效期
上面设置cookie使用的是session cookie,即关闭浏览器cookie就会丢失,下次访问时需要重新认证,但是这不能阻挡用户故意存储票据用于下次访问。理论上accesstoken是有个过期时间的。在casdoor服务端上配置,这里需要有一定的机制来保证用户的票据在超过过期时间expires_in之后无效。
cookie内容合法性
上面的middleware仅仅校验了cookie中是否存在user信息,并没有校验用户的合法性。页面是可以篡改cookie数据的,比如将用户id、name替换,如果后端直接使用cookie中的user信息,就会有安全风险。
更加合适的做法是将accesstoken当做票据,并在middleware中校验accesstoken的有效性。使其承担起接入层的作用。accesstoken可以访问cosdoor去校验,或者在业务服务端存储,基本不可能伪造(但是也有被共享的可能)。
参考Casnode示例。使用了session来存储ParseJwtToken()的claim结果,里面包换了accesstoken以及用户信息。
票据更新
理论上accesstoken的过期时间不应该太长,比如2小时。然后通过票据刷新接口定期刷新accesstoken,避免使用过程中的泄露。
吐槽
在自己的接入SDk的过程中,发现一些小的问题。
- SDK参数各异:比如js版前后端版本的SDK,url、org都能有两种写法
- SDK鉴权方式差异,在官方文档中,前后端鉴权所需的参数还挺大的。在我看来使用的目的相同,都是取用户资料,为何后端还需要cert、secret key等,而前端sdk啥也不用?cert、secret这种是否有必要并存。
- SDK能力不完善。个人项目是使用nextjs,安全考虑,期望是将accsstoken获取、解析放在后端,避免jwt透传。提供的next SDK仅在client component下可用,server端根本没办法使用。转而使用node版本的SDK,发现在next下无法使用(依赖的 jsonwebtoken 在next 环境不兼容)。
总结
以上就是casdoor的用户认证基础流程,基础的用户认证管理接入还是挺简单的。casdoor还提供了不少其他能力,包括商品管理&教育、用户群组管理。