OpenProject 开发实战:用 Docker 容器化 SAML idP 快速搭建本地 SSO 联调环境
2026/9/14 16:30:19 网站建设 项目流程

OpenProject 开发实战:用 Docker 容器化 SAML idP 快速搭建本地 SSO 联调环境

【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openproject

本文聚焦 OpenProject 官方开发文档中的 SAML 开发环境搭建指南:如何在本地开发实例中,用容器化的 SimpleSAMLphp 身份提供商(idP)完成 SAML SSO 的端到端联调。读完后,你将掌握users.php属性配置、docker 环境变量(SP Entity ID、ACS 回调地址、SLO 地址)的完整含义、configuration.yml中 SAML 各配置项与 OpenProject 源码字段的对应关系,并能用两个内置测试账号验证登录与登出全流程。

一、这份指南的适用范围

该指南(docs/development/saml/README.md)明确指出:仅面向 OpenProject 开发者本地联调,不是生产环境的 SAML 接入指南。生产/管理侧的 SAML 配置请参见 系统管理员 SAML 文档。

核心思路是:使用现成的测试 idP 镜像kristophjunge/test-saml-idp(内含 SimpleSAMLphp),通过挂载自定义authsources.php补充 OpenProject 期望接收的属性,再以 OpenProject 作为 SP(服务提供方)完成标准 SAML 2.0 断言流程。

前置条件:

  • 一套可用的 Docker 环境;
  • 一套可自由修改配置的 OpenProject 开发实例。

二、编写补充属性的 users.php

容器内自带的 SimpleSAMLphp 默认用户配置缺少 OpenProject 需要的一批默认属性,因此官方指南要求在本地新建一个saml-idp目录,并写入如下users.php(该文件稍后会挂载为容器内的authsources.php):

<?php $config = array( 'admin' => array( 'core:AdminPassword', ), 'example-userpass' => array( 'exampleauth:UserPass', 'user1:user1pass' => array( 'uid' => 'user1', 'givenName' => 'foo', 'sn' => 'bar', 'eduPersonAffiliation' => array('group1'), 'email' => 'user1@example.com', ), 'user2:user2pass' => array( 'uid' => 'user2', 'givenName' => 'user', 'sn' => 'second', 'eduPersonAffiliation' => array('group2'), 'email' => 'user2@example.com', ), ), );

这里为两个测试账号(user1/user1passuser2/user2pass)分别声明了uidgivenNamesneduPersonAffiliationemail五类属性。这些属性名并非随意命名——它们正是 OpenProject 侧 SAML 属性映射的默认取值。从源码看,默认映射常量 中内置了邮箱(mail/email/emailAddress等)、名字(givenName等)、姓氏(sn/surname等)的候选属性列表,开发文档中的attribute_statements也是按uid → logingivenName → first_namesn → last_nameemail → email来映射的,二者完全吻合,这也是"默认用户配置缺属性就收不到用户"这一说法的直接来源。

三、启动 SAML idP 容器

saml-idp目录中执行(本机开发环境,OpenProject 运行在localhost:3000):

mkdir saml-idp && cd saml-idp
docker run \ -p 8080:8080 \ -p 8443:8443 \ -e SIMPLESAMLPHP_SP_ENTITY_ID=http://localhost:3000 \ -e SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://localhost:3000/auth/saml/callback \ -e SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE=http://localhost:3000/auth/saml/slo \ -v $(pwd)/users.php:/var/www/simplesamlphp/config/authsources.php \ --network host \ kristophjunge/test-saml-idp

如果不是标准开发实例,需要把三个环境变量中的http://localhost:3000替换为你的 OpenProject 实际主机名:

docker run \ -p 8080:8080 \ -p 8443:8443 \ -e SIMPLESAMLPHP_SP_ENTITY_ID=http://<YOUR OPENPROJECT HOSTNAME> \ -e SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=http://<YOUR OPENPROJECT HOSTNAME>/auth/saml/callback \ -e SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE=http://<YOUR OPENPROJECT HOSTNAME>/auth/saml/slo \ -v $(pwd)/users.php:/var/www/simplesamlphp/config/authsources.php \ --network host \ kristophjunge/test-saml-idp

各参数含义(结合源码印证):

参数含义
-p 8080:8080idP 的 HTTP SSO 入口,对应下文 SP 配置中的idp_sso_target_url
-p 8443:8443idP 的 HTTPS 端口(SimpleSAMLphp 默认启用 TLS 演示)
SIMPLESAMLPHP_SP_ENTITY_ID告诉 idP:SP 的 Entity ID 是什么。对应 OpenProject 的sp_entity_id/issuer字段
SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE断言回调地址(ACS),即 OpenProject 的/auth/saml/callback。源码中该地址由AuthProvider#callback_url生成,Saml::Provider 通过assertion_consumer_service_url委托给callback_url提供
SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE单点登出(SLO)地址/auth/saml/slo
-v $(pwd)/users.php:/var/www/simplesamlphp/config/authsources.php用自定义用户/属性配置覆盖容器默认的 authsources
--network host直接使用宿主机网络,保证localhost可达

四、在 configuration.yml 中配置 OpenProject 侧 SAML

在 OpenProject 的config/configuration.yml中加入如下最小配置(完整示例可参考 config/configuration.yml.example):

default: saml: name: "saml" display_name: "simplesaml-docker" # 使用默认 SAML 图标 icon: "auth_provider-saml.png" # omniauth-saml 配置 assertion_consumer_service_url: "http://localhost:3000/auth/saml/callback" issuer: "http://localhost:3000" idp_cert_fingerprint: "119b9e027959cdb7c662cfd075d9e2ef384e445f" idp_sso_target_url: "http://localhost:8080/simplesaml/saml2/idp/SSOService.php" idp_slo_target_url: "http://localhost:8080/simplesaml/saml2/idp/SingleLogoutService.php" attribute_statements: email: ['email'] login: ['uid'] first_name: ['givenName'] last_name: ['sn']

逐项说明:

  • name/display_namename是内部标识(用于生成/auth/saml这类 OmniAuth 路由前缀),display_name是登录页上显示的名称。重启后登录按钮即显示为 "simplesaml-docker";
  • assertion_consumer_service_url:SP 接收断言的回调 URL,必须与容器侧SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE完全一致;
  • issuer:SP Entity ID,对应容器侧的SP_ENTITY_ID
  • idp_cert_fingerprint:测试 idP 证书的 SHA-1 指纹。注意 OpenProject 同时支持完整证书 PEM——Saml::Provider 中idp_cert是首选字段,idp_cert_fingerprint仅作为旧版本的回退兼容保留,UI 上已不再提供指纹入口;
  • idp_sso_target_url:idP 的 SSO 入口,即容器 8080 端口下的SSOService.php
  • idp_slo_target_url:idP 的单点登出入口SingleLogoutService.php
  • attribute_statements:声明"OpenProject 需要的字段 ← idP 断言中的哪个属性"的映射,与users.php中的属性名一一对应。

从源码结构看,configuration.yml中的这些键最终会被 HashBuilder#to_h 转换为 omniauth-saml 的策略参数:attribute_statementsformatted_attribute_statements拆分(支持多属性候选,按换行分隔)、idp_cert_fingerprint/idp_certidp_cert_options_hash决定用证书还是指纹校验,再合并security_options_hash(签名/摘要算法、want_assertions_signed等)后交给 omniauth-saml 使用。

如果你的 OpenProject 不跑在localhost:3000,需要把assertion_consumer_service_urlissuer换成本机实际主机名;如果 idP 不在本机,idp_sso_target_urlidp_slo_target_url也要同步调整。官方建议两端都放本地,最省事。

五、验证登录与底层调用链

重启 OpenProject 后,登录页会出现名为 "simplesaml-docker" 的按钮,点击后被重定向到 SimpleSAMLphp 容器,使用以下任一账号登录:

  • 登录名user1,密码user1pass
  • 登录名user2,密码user2pass

登录成功的背后调用链在 AuthSaml 引擎注册代码 中可以看到:每个可用 provider 的配置被转换为一个 omniauth-saml 策略;retain_from_session会把saml_uidsaml_session_indexsaml_transaction_id暂存会话,供后续登出使用;single_sign_out_callback则检查会话中是否存在这两个字段,存在时恢复它们并重定向到omni_auth_start_path(...)/spslo,从而走 SP 发起的 SLO 流程——这解释了为什么idp_slo_target_url和容器侧SP_SINGLE_LOGOUT_SERVICE两侧都要配置。

另外两点值得注意的源码事实:

  • provider 的"可用"判定由 configured? 与 mapping_configured? 控制:sp_entity_ididp_sso_service_url、idP 证书(或指纹)齐备才算配置完成,mapping_login/mail/firstname/lastname四项映射齐备才算映射完成。上面configuration.yml恰好把这三类字段配齐,因此可直接通过;
  • 该方式(configuration.yml+seed)适合开发环境;产品化路径是在后台"身份与访问 → SAML 提供方"页面管理 provider,对应路由见 modules/auth_saml/config/routes.rb,并支持从 idP 的 metadata URL/XML 自动导入实体 ID、SSO/SLO 地址与证书(相关服务位于 metadata_fetcher.rb 与 update_metadata_service.rb)。开发文档走静态配置是为了最小化步骤,两者殊途同归。

六、常见问题速查

现象排查点
登录页没有 "simplesaml-docker" 按钮configuration.yml未重启生效;或 provider 未通过configured?(缺少 idP 证书/指纹)
断言 400/签名错误issuer与容器SP_ENTITY_ID不一致;或idp_cert_fingerprint换证书后未更新
登录成功但用户字段为空attribute_statements的属性名与users.php实际下发的属性不匹配
登出后 idP 会话仍在检查idp_slo_target_urlSIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE是否两侧对齐

这套"容器 idP + 最小 YAML 配置"的组合,让你无需任何企业级 IdP 就能在本地完整复现 SAML 登录、属性映射与单点登出,是开发 OpenProject 认证相关功能时最便捷的联调基座。

【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openproject

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询