共计 8181 个字符,预计需要花费 21 分钟才能阅读完成。
背景
用户管理是多平台项目一直以来的痛点。不同平台之间用户割裂,各自维护一套单一密码。
我在家中也维护了许多服务,例如堡垒机、GitLab、Harbor、Jenkins、Grafana、夜莺等等。接入一套统一鉴权平台托管用户模块可以降低用户管理的复杂度。
CasDoor 是什么
CasDoor 是一个基于 OAuth 2.0 / OIDC 的身份认证和管理平台(Identity Access Management,IAM)。
它能够提供多种认证方式:
- 用户名/密码、手机验证码、邮箱验证码、2FA
 - 支持第三方登录(GitHub、Google、微信等)
 - 支持多种验证方式,例如SSO、auth0、CAS等
 - 提供用户管理和权限管理功能
 
部署
IP:192.168.2.10
Docker Compose
参考链接:casdoor.org/zh/docs/basic/try-with-docker、github.com/casdoor/casdoor
官方文档提供的 docker-compose.yml 还需要自行构建镜像,用起来不方便。
支持多种数据库驱动。
数据库使用 Postgres :
mkdir /usr/local/casdoor && cd /usr/local/casdoor
# vim docker-compose.yml
version: '3'
services:
  casdoor:
    image: casbin/casdoor:latest
    container_name: casdoor
    entrypoint: /bin/sh -c './server --createDatabase=true'  # 关键配置:自动创建数据库表
    ports:
      - "8011:8000"
    depends_on:
      casdoor-postgres:
        condition: service_healthy
    environment:
      RUNNING_IN_DOCKER: "true"
      driverName: "postgres"
      dataSourceName: 'user=postgres password=thisispassword123 host=casdoor-postgres port=5432 sslmode=disable dbname=casdoor'
      origin: "http://192.168.2.10:8011"
      runmode: 'dev'
    volumes:
      - ./init_data.json:/init_data.json
    restart: unless-stopped
  casdoor-postgres:
    image: postgres:17-alpine
    container_name: casdoor-postgres
    environment:
      POSTGRES_PASSWORD: "thisispassword123"
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    ports:
      - "5433:5432"
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U postgres']
      interval: 5s
      timeout: 5s
      retries: 5
    restart: always
# docker-compose up -d 
# docker-compose ps 
数据库使用 MySQL:
# vim docker-compose.yml
version: '3'
services:
  casdoor:
    image: casbin/casdoor:latest
    container_name: casdoor
    entrypoint: /bin/sh -c './server --createDatabase=true'  # 关键配置:自动创建数据库表
    ports:
      - "8011:8000"
    depends_on:
      - casdoor-mysql
    environment:
      RUNNING_IN_DOCKER: "true"
      driverName: "mysql"
      dataSourceName: "root:testpassword123@tcp(casdoor-mysql:3306)/"
      dbName : "casdoor"
      origin: "https://***casdoor.opshub.cn:"
    restart: unless-stopped
  casdoor-mysql:
    image: mysql:8.0.25
    container_name: casdoor-mysql
    environment:
      MYSQL_ROOT_PASSWORD: "testpassword123"
      MYSQL_DATABASE: "casdoor"
    volumes:
      - ./mysql_data:/var/lib/mysql
    ports:
      - "3376:3306"
    restart: unless-stopped
# docker-compose up -d 
# docker-compose ps 
默认账号:admin
默认密码:123
Nginx 反代
参考链接:casdoor.org/zh/docs/deployment/nginx/
# cat /etc/nginx/conf.d/***.opshub.cn.conf 
upstream casdoor {
  server 192.168.2.10:8011;
}
server {
  listen 80;
  server_name ***.opshub.cn;
  return 301 https://$server_name$request_uri;
}
server {
  listen 443 ssl;
  http2 on;
  server_name ***.opshub.cn;
  ssl_certificate     /root/.acme.sh/*.opshub.cn/fullchain.cer;
  ssl_certificate_key /root/.acme.sh/*.opshub.cn/*.opshub.cn.key;
  ssl_session_timeout 5m;
  ssl_protocols TLSV1 TLSv1.1 TLSv1.2;
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_prefer_server_ciphers on;
  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_set_header X-Forwarded-Proto https;
    proxy_redirect http:// https://;
    proxy_pass http://casdoor;
  }
}
配置好dns解析后,使用浏览器访问域名验证:
使用
CasDoor 的配置项很繁杂,下文以简单案例演示,只进行必要的配置快速接入。
服务端配置
修改默认密码:
访问链接:CASDOO_RDOMAIN/account
创建组织:
用户管理 –> 组织 –> 添加组织 –> organization_pyw_test
创建测试用户:
用户管理 –> 用户 –> 添加用户:pyw-test
其他配置保持默认。
创建应用:
身份认证 –> 应用 –> 添加应用
每个应用对应了不同的接入客户端,需要配置不一样的重定向 URLs 及其他配置项。后续章节展开说明。
客户端接入
CasDoor 提供了多种接入方式:casdoor.org/zh/docs/category/how-to-connect-to-casdoor
- 标准 OIDC 客户端:支持 OpenID Connect (OIDC),这是一个基于 OAuth2 协议的身份层,用于简化身份验证流程。
 - Casdoor SDKs:使用 Casdoor SDKs 而不是标准的 OIDC 协议。
 - Casdoor Authenticator App:在 Casdoor 中存储 TOTP 代码。
 - 单点登录
 - LDAP:支持 LDAP(轻量级目录访问协议),这是一种用于访问和维护分布式目录信息服务的协议。
 - Vue SDK:Casdoor 提供的 Vue SDK。
 - 桌面 SDK
 - 移动 SDKs
 - Casdoor 插件:在 Spring Boot、WordPress、Odoo 等其他框架中使用 Casdoor 插件或中间件。
 - Next.js:在 Next.js 项目中使用 Casdoor。
 - Nuxt:在 Nuxt 项目中使用 Casdoor。
 - OAuth 2.0:支持 OAuth2 协议,允许第三方应用通过授权码模式、密码模式、客户端模式等获取访问令牌(Access Token)。
 - CAS :支持 CAS(Central Authentication Service),这是一种单点登录(SSO)协议,用于在多个应用之间共享用户身份。
 - SAML:支持 SAML2 协议,这是一种基于 XML 的开放标准,用于在不同系统之间交换认证和授权数据。
 - 面部识别:使用 Face ID 登录到 Casdoor。
 - API:提供了 RESTful API,允许开发者直接通过 API 进行用户管理和身份验证。
 
不同客户端应用支持的验证方式不一致,得益于 CasDoor 提供了完备的接入方式,下文一一介绍。
需要注意的是此处 CasDoor 的设计不太好,CAS 接入方式的名称字段作为了唯一标志。
JumpServer
Jumpserver 支持 基本、LDAP、CAS、Passkey 登录方式接入,以 CAS 为例。
在 CasDoor 创建应用:jumpserver
回调地址:https://JUMPSERVER_DOMAIN
Jumpserver 安全设置: 取消勾选仅存在用户登录
系统设置 — > 安全设置
Jumpserver 认证设置:CAS接入
系统设置 –> 认证设置
登陆验证:
夜莺
夜莺支持 OAuth2、LDAP、CAS 、OIDC 四种登录方式接入,以 CAS 为例。
在 CasDoor 创建应用:n9e
回调地址:https://N9E_DOMAIN/callback/cas
其他配置保持默认。
夜莺配置:CAS接入
# 是否启用 CAS 登录功能 参数选项 true/false
Enable = true
# CAS 登录方式在前端显示的名称
DisplayName = 'CAS登录'
# CAS 认证成功后的重定向URL。这个URL应该是夜莺监控服务的回调地址
RedirectURL = 'https://***.opshub.cn/callback/cas'
# SSO 服务 cas 的地址
SsoAddr = 'https://***.opshub.cn/cas/organization_pyw_test/n9e'
# SSO 服务 cas 的登出地址,用于处理用户退出登录的请求
#SsoLogoutAddr = 'https://***.opshub.cn/cas/organization_pyw_test/n9e/logout'
# SSO 服务 cas 登录的 path;与 SsoAddr 拼接得到完整的登录地址
LoginPath = '/login'
# 是否覆盖用户属性 参数选项 true/false
CoverAttributes = true
# 用户在夜莺系统中的默认角色 Guest/Standard/Admin
DefaultRoles = ['Standard']
# 请求的 CAS 范围
Scopes = ['openid', 'profile', 'email', 'phone']
# CAS 的用户属性映射 n9e 的用户属性
[Attributes]
# 用户名字段的映射
Username = 'sub'
# 昵称字段的映射
Nickname = 'nickname'
# 电话字段的映射
Phone = 'phone_number'
# email 字段映射
Email = 'email'
登录验证:
Grafana
参考链接:grafana.com/docs/grafana/latest/setup-grafana/configure-security…
Grafana 支持多种身份验证方式,以 Generic OAuth2 为例。
在 CasDoor 创建应用:grafana
回调地址:https://GRAFANA_DOMAIN/login/generic_oauth
grafana 服务端配置:
# vim /etc/grafana/grafana.ini
[auth.generic_oauth]
enabled = true
name = Casdoor
client_id = ba93935384c77a0e8125
client_secret = b80847a0aab3c5d00469c2fa267abf87f119b4b7
scopes = user:email read:org
auth_url = https://***.opshub.cn/login/oauth/authorize
token_url = https://***.opshub.cn/api/login/oauth/access_token
api_url = https://***.opshub.cn/api/userinfo
allow_sign_up = true
# 使Grafana不同步Casdoor的用户权限,否则Grafana不能修改使用Casdoor接入用户的权限
skip_org_role_sync = true
oauth_skip_org_role_update_sync = true
登录验证:
GitLab
参考链接:casdoor.org/zh/docs/integration/ruby/gitlab/、blog.csdn.net/weixin_52270081/article/details/144580436
以OIDC接入为例。
在 CasDoor 创建应用:gitlab
回调地址:https://GITLAB_DOMAIN/users/auth/openid_connect/callback
其他配置保持默认
gitlab 服务端配置:
# vim ./config/gitlab.rb
external_url 'https://***.opshub.cn'
nginx['listen_port'] = 30080
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
  "X-Forwarded-Proto" => "https",
  "X-Forwarded-Ssl" => "on",
  "Host" => "$http_host",
  "X-Real-IP" => "$remote_addr",
  "X-Forwarded-For" => "$proxy_add_x_forwarded_for"
}
gitlab_rails['gitlab_username_changing_enabled'] = false
gitlab_rails['omniauth_auto_link_user'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['openid_connect']
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_providers'] = [
    {
        name: "openid_connect",
        label: "Casdoor", # 可选的登录按钮标签,默认为 "Openid Connect"
        args: {
            name: "openid_connect",
            scope: ["openid", "profile", "email"],
            response_type: "code",
            issuer:  "https://***.opshub.cn",
            client_auth_method: "query",
            discovery: true,
            uid_field: "preferred_username",
            client_options: {
                identifier: "77999c17d50484500b55",
                secret: "f5550466c7ad0f35efc0873a46839d7574192470",
                redirect_uri: "https://***.opshub.cn/users/auth/openid_connect/callback"
            }
        }
    }
]
# 重建配置并重启服务
# gitlab-ctl reconfigure
# gitlab-ctl restart
登录验证:
Jenkins
参考链接:casdoor.org/zh/docs/integration/java/jenkins-oidc/
以OIDC接入为例。
在 CasDoor 创建应用:jenkins
回调地址:https://JENKINS_DOMAIN/securityRealm/finishLogin
Jenkins 服务端配置:
需要注意,当 Jenkins 配置第三方接入方式后,无法再支持本地验证。所以在配置时注意现将授权策略配置为:允许授权用户做任何事,避免第三方接入账号权限不够,而默认的admin又无法登陆。
最好在执行配置前进行备份。
Dashboard –> 系统管理 –> 插件管理 –> Available plugins –> 安装 OpenId Connect Authentication
系统管理 –> 全局安全配置
自动发现ODIC配置URL:https://CASDOOR\_HOSTNAME/.well-known/openid-configuration
登录验证:
Harbor
关于如何部署 Harbor,可参考站内文章:Harbor 镜像仓库部署
Harbor 默认登录方式为本地数据库:postgres。如果本地数据库中已经存在除 admin/anonymous 之外的用户,则不能再直接修改认证方式。
将现有用户在数据库中删除后,才能够进行修改。只在web控制端上删除用户仅是添加了一个删除tag,必须在数据库中执行物理删除。
删除用户为破坏性操作,生产环境评估后再执行。
删除前:
# 进入容器
docker exec -it harbor-db /bin/bash
# 登录数据库
psql -U postgres -d registry
# 查找用户
select * from harbor_user;
# 删除用户
delete from harbor_user where username='my-wordpress';
delete from harbor_user where username='jenkins-my-wordpress';
删除后:
此时 Harbor web端才能正常选择认证模式:
参考链接:goharbor.io/docs/1.10/administration/configure-authentication/oi…
以 OIDC 接入为例。
在 CasDoor 创建应用:harbor
回调地址:https://HARBOR_DOMAIN/c/oidc/callback
Harbor 服务端配置:
可以看到有一行提示:`请确保将OIDC提供的重定向地址设置为 http://192.168.2.10:8083/c/oidc/callback`
由于我使用了外部nginx反向代理harbor,所以需要修改配置文件:
# vim harbor.yml
hostname: ***.opshub.cn
external_url: https://***.opshub.cn
# 生成配置
./prepare
# 重启服务
docker-compose down -v
docker-compose up -d
页面提示会发生变化:
登录验证:
总结
文章介绍了6个平台的简单接入,实际生产使用需要进行更多配置项的评估,例如用户组、权限等,确保认证安全。
引用链接
- casdoor.org/zh/docs/basic/try-with-docker
 - github.com/casdoor/casdoor
 - casdoor.org/zh/docs/deployment/nginx/
 - casdoor.org/zh/docs/category/how-to-connect-to-casdoor
 - grafana.com/docs/grafana/latest/setup-grafana/configure-security...
 - casdoor.org/zh/docs/integration/ruby/gitlab/
 - blog.csdn.net/weixin_52270081/article/details/144580436
 - casdoor.org/zh/docs/integration/java/jenkins-oidc/
 - Harbor 镜像仓库部署
 - goharbor.io/docs/1.10/administration/configure-authentication/oi...