做过企业内部平台的同学大概率都有过这种经历OA 一套账号、财务系统一套账号、项目管理工具再注册一次再加上各种内部服务后台光记住密码就能把人的耐心磨没。更麻烦的是每个系统还得单独做密码找回、账号禁用、离职清理运维起来像在补窟窿。我最早接手这类需求时也走了不少弯路后来用了 Hadess 做统一认证入口又把公司全员日常使用率最高的钉钉接进去才算是把这个问题彻底理顺。Hadess 是一个开源的身份认证与统一登录平台核心解决的就是“多系统重复登录”和“账号身份不统一”这两件事。它支持 OAuth2、OIDC 这类标准协议也内置了针对钉钉的组织连接器可以直接把钉钉里的员工身份、部门信息同步过来实现扫码或跳转授权登录。无论你是负责公司内部平台的后端开发还是正在给团队搭建统一门户的运维同学都可以参考这篇指南从零跑通 Hadess 钉钉集成的完整链路。1. 为什么要把钉钉变成统一认证入口1.1 身份孤岛一个公司 N 套密码大多数成长型公司里的系统不是一次性建好的而是随着业务发展一个一个“长”出来的。行政上了一个 OA财务上了一个审批系统研发部门自己搭了 Wiki 和代码仓库人事那边又买了 SaaS 版的人力资源软件。每套系统各自维护自己的用户表员工每进一个新系统就要重新注册一次。这就导致三个非常现实的问题。第一员工使用成本高账号密码记不住于是到处贴便签、用同一个密码安全隐患反而更大。第二IT 管理成本高一个员工入职要开五六个账号离职要挨个系统去禁用漏掉一个就可能留下后门。第三数据不互通同一个人的信息在 A 系统里叫“张三”在 B 系统里叫 zhangsan甚至手机号还不一致做跨系统数据汇总时根本对不上人。做统一认证登录不是为了让某个系统更好用而是为了解决这整条链路的问题。让一套身份认证源去对接所有业务系统其他系统不再各自维护“用户名密码”而是统一信任 Hadess 签发的身份凭证。1.2 统一认证背后的标准流程统一认证听起来很高端但它背后的原理并不复杂。你可以把它理解成公司前台换了一张“访客卡”员工进门先向前台做一次身份核验前台确认后发一张临时通卡之后去会议室、去食堂、进办公区都不需要再重复登记各个门禁认的是这张通卡。在技术实现上Hadess 扮演的就是“前台”的角色。用户访问业务系统时业务系统发现没有登录态就把用户重定向到 HadessHadess 要求用户登录用户完成密码输入或钉钉扫码Hadess 校验通过后给业务系统返回一个授权凭证业务系统再用这个凭证到 Hadess 换取用户信息并建立自己的会话。这套流程在 OAuth2 里叫做授权码模式也是目前用得最广泛的一种方式。它最大的好处是用户密码不会经过业务系统密码变更、找回、强制重置都集中在 Hadess 一处处理业务系统只需要关心“这个人是否已通过认证”以及“他有哪些权限”。1.3 为什么选择钉钉作为身份源统一认证解决了“账号怎么打通”的问题紧接着就有一个新问题以哪套系统里的身份作为基准有些团队希望自建用户体系从零做起角色权限模型这套路径灵活但成本不低。更多企业内部已经普遍使用钉钉办公员工入职时人事就已经在钉钉里创建了账号部门、岗位、手机号都是现成的。把钉钉作为身份源有几个天然优势。第一员工实名认证程度高手机号、姓名、部门都与真实组织架构强绑定。第二钉钉的组织架构本身就是一棵现成的部门树对应到系统里的角色和权限分组非常直观。第三员工对钉钉的使用习惯已经养成扫码授权几乎没有学习成本。相比让员工再去记一个内部平台的复杂密码用钉钉扫一扫就能进入所有系统体验完全不在一个层级。这就引出了 Hadess 中最关键的一环把钉钉连接进来让钉钉成为整个统一认证体系的“身份证颁发机构”。2. Hadess 快速部署与基础配置2.1 部署前的清单动手部署之前先确认三样东西一台能长期运行的主机、一个可供外部访问的域名、一个数据库。主机推荐 2 核 4G 以上的配置Hadess 本身不重但考虑到要承担公司所有系统的认证分发内存和带宽别太省。域名是必须的因为钉钉回调地址要求使用 HTTPS 域名如果暂时没有正式域名内网测试环境可以用暂存域名或内网穿透工具临时顶着生产环境强烈建议直接上正式域名。数据库方面Hadess 默认支持 PostgreSQL 和 MySQL生产环境我建议优先用 PostgreSQL。原因不复杂身份认证系统涉及大量事务性写入PostgreSQL 在高并发写入和事务一致性上更稳。开发环境图省事的话可以直接用 Docker 里自带的一个最小化配置先把服务跑起来再说。确认完这三点我们再看端口规划。Hadess 默认监听 8080 端口前面建议再套一层 Nginx 做 HTTPS 终止把 443 端口转发到 8080。之后在钉钉开放平台配置回调地址时填的是 Nginx 对外暴露的 HTTPS 地址而不是内网 IP。2.2 Docker Compose 一键启动用 Docker Compose 部署是个人觉得最省心的方式。先新建一个目录比如hadess-demo然后在里面创建一个docker-compose.yml文件version: 3.8 services: hadess: image: hadess/hadess:latest container_name: hadess restart: unless-stopped ports: - 8080:8080 environment: HADESS_ISSUER_URL: https://auth.example.com HADESS_DB_TYPE: postgres HADESS_DB_HOST: db HADESS_DB_PORT: 5432 HADESS_DB_NAME: hadess HADESS_DB_USER: hadess HADESS_DB_PASSWORD: change_me_strong_password HADESS_ADMIN_INITIAL_PASSWORD: change_me_admin_password depends_on: db: condition: service_healthy db: image: postgres:15-alpine container_name: hadess-db restart: unless-stopped environment: POSTGRES_DB: hadess POSTGRES_USER: hadess POSTGRES_PASSWORD: change_me_strong_password volumes: - hadess-db-data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U hadess -d hadess] interval: 10s timeout: 5s retries: 5 volumes: hadess-db-data:我用 Compose 的方式部署过好几套类似系统这种做法的好处是环境依赖收敛得很干净数据库、应用启动顺序都由编排工具管理升级时直接更新镜像版本再docker compose up -d回滚也方便。启动命令很简单docker compose up -d等上几十秒容器正常启动后打开http://服务器IP:8080应该能看到 Hadess 的登录页。如果你的防火墙开通了 8080 端口这一步通常不会有什么问题。如果页面迟迟打不开先docker compose logs hadess看一下容器日志最常见的错误是数据库连接失败检查一下配置文件里的数据库密码是否一致。2.3 初始化管理员与基础参数首次启动后系统会在数据库中自动创建管理员账号默认用户名是admin密码来自环境变量HADESS_ADMIN_INITIAL_PASSWORD。登录进去的第一件事建议立刻进入个人中心修改管理员密码并创建一个专用的运维管理员账号避免长期使用初始化口令。接下来需要配置系统的发行者地址issuer URL。这个配置非常关键Hadess 生成令牌和回调地址时都会用到它。在系统管理 - 基础设置里把发行者地址改成对外访问的 HTTPS 地址例如https://auth.example.com。如果这里填错了后续钉钉回调地址、业务系统拉起认证时拼接出来的 URL 都会是错的排查起来非常痛苦。基础参数里还有几个值得关注的选项会话过期时间默认 8 小时企业内部系统可以按需调整我一般设置为 12 小时兼顾安全性和用户体验。允许注册生产环境务必关闭所有账号都走钉钉同步和导入。登录失败锁定策略建议开启连续失败 5 次锁定 15 分钟防止暴力破解。2.4 验证服务状态配置完这些基础项做一个简单的连通性验证。在 Hadess 的“健康检查”或“系统状态”页面确认数据库连接状态显示为正常发行者地址可以正常访问。也可以在命令行里直接请求一下认证端点验证服务是否按预期响应curl -I https://auth.example.com/.well-known/openid-configuration如果返回 200 并且响应头里带有content-type: application/json说明 Hadess 的 OIDC 服务已经正常跑起来了。这个地址也是后面配置业务系统时必须用到的基础信息很多 SDK 会自动从这个地址拉取认证配置。3. 钉钉集成的完整配置过程3.1 在钉钉开放平台创建企业应用钉钉侧的工作要到钉钉开放平台后台去操作。首先进入钉钉开放平台找到“应用开发”-“企业内部应用”点击创建应用。应用类型选择“企业内部应用”名称可以叫“统一认证平台”Logo 随便传一张即可。创建完成后进入应用详情页找到“凭证与基础信息”这里有两个关键参数AppKey和AppSecret。AppKey 是应用的身份标识AppSecret 相当于密码两者都需要在后续填入 Hadess。特别提醒一句AppSecret 只在创建时完整显示一次后续再次查看可能会被脱敏处理第一次看到时就要复制保存好。接下来配置权限范围。在“权限管理”里把以下权限点授予这个应用个人手机号信息个人邮箱信息企业员工个人信息部门信息读取成员信息读取权限点没有开通的话后续拉起钉钉授权时虽然能扫码但会拿不到手机号、邮箱这些关键信息用户资料同步就会缺字段。这一步是最容易遗漏的宁可全部勾上再按需收敛也别不勾。最后配置回调地址。在“登录与分享”或“扫码登录”配置里把回调地址指向 Hadess 的钉钉连接器回调端点格式一般是https://auth.example.com/oauth/callback/dingtalk如果只做网页扫码登录配置这一条回调地址就够了。如果你还想支持钉钉内免登跳转需要额外配置一个免登回调地址不过我们大多数人第一步用扫码登录就足够了。3.2 Hadess 侧创建钉钉身份提供者回到 Hadess 管理后台进入“身份提供者”或“SSO 配置”菜单选择添加“钉钉”。这里我们需要把刚才从钉钉开放平台拿到的参数对应填进去配置项填写内容说明应用名称DingTalk显示名用于在登录页展示AppKey从钉钉开放平台复制钉钉应用的身份标识AppSecret从钉钉开放平台复制钉钉应用的密钥保存时注意安全回调地址由 Hadess 自动生成需与钉钉侧配置保持一致授权范围openid, profile, email, phone决定能拉取到哪些用户信息填完之后点击“保存”并做一次连通性测试。Hadess 一般会提供一个“测试连接”按钮内部会尝试调用钉钉开放接口如果 AppKey、AppSecret 正确且权限点已开通测试会显示成功。若测试失败优先检查权限点是否开通再检查服务器是否能正常访问钉钉开放平台接口。3.3 字段映射与授权范围配置配置好连接器之后最关键的一步是把钉钉返回的用户字段映射到 Hadess 的本地用户模型。钉钉接口在用户授权后返回的信息主要包括unionid、openid、userid、name、avatar、mobile、email其中unionid是用户在整个钉钉开放平台范围内的唯一标识稳定性最好用它作为 Hadess 用户的唯一性判断依据是最稳妥的。字段映射建议这样设置钉钉unionid映射到 Hadess 用户的外部ID用于判断用户是否已存在。钉钉name映射到显示名称。钉钉mobile映射到手机号。钉钉email映射到邮箱如果钉钉里未维护邮箱可以留空后续手动补充。钉钉部门ID和职位可以映射为自定义属性后续用于角色分组。这里有一个容易踩的坑用openid做唯一性判断不够保险。openid是钉钉应用维度的用户标识同一个用户在不同应用里openid不同一旦以后换了应用重新对接之前建立的账号关联就全部失效了。我第一次对接时就吃过这个亏后来统一改成unionid才算彻底稳定。授权范围的配置和字段映射是配套的。如果映射了邮箱但钉钉侧没分配“个人邮箱信息”的权限点拉回来的邮箱字段就是空的。所以先检查钉钉侧权限再配置映射顺序不要反过来。3.4 一次完整的统一登录流程所有配置就绪后钉钉集成登录流程是这样的用户访问业务系统首页业务系统检测到未登录重定向到 Hadess 的统一登录页。登录页上除了用户名密码输入框还会有一个“使用钉钉登录”的按钮。用户点击后Hadess 构造一条授权请求把用户引导到钉钉开放平台的授权页。此时用户可以选择两种方式完成认证。第一种是输入钉钉账号密码登录第二种是使用钉钉 App 扫码确认。无论哪种方式钉钉在验证用户身份后都会把浏览器重定向回之前配置的 Hadess 回调地址并在 URL 后面带上一个临时授权码。Hadess 收到授权码后用该授权码向钉钉换取访问令牌再调用钉钉的用户信息接口拿到用户资料。拿到资料后按照字段映射规则匹配本地用户如果之前已经绑定过账号直接建立会话如果是第一次登录则自动在 Hadess 中创建一个新用户并把钉钉资料填充进去。整个流程结束后浏览器会被重定向回最初想要访问的业务系统。业务系统发现通过认证后再向 Hadess 询问“这个人是谁”并建立自己的本地会话。从用户视角来看整个过程只需扫码一次后续访问其他接入系统的时不再重复扫码因为 Hadess 的会话已经建立。3.5 让业务系统接入 Hadess钉钉连接器配置好了不代表所有系统就自动打通了。每个业务系统还需要各自接入 Hadess一般有两种方式。第一种方式是使用标准 OIDC 协议接入。几乎所有主流的现代化框架都支持 OIDC 客户端比如 Spring Boot 里的spring-boot-starter-oauth2-client、前端项目里的oidc-client-ts。接入时只需要提供 Hadess 的发现地址、客户端 ID、客户端密钥和回调地址SDK 就能自动完成认证跳转和令牌校验。第二种方式是使用网关统一接入。如果业务系统是老系统改不动代码可以在网关层接一层认证。网关拦截所有未认证请求重定向到 Hadess 认证认证通过后再把用户身份信息以请求头的方式转发给后端系统。这种方式对业务代码侵入最小但需要确保老系统能够信任网关传递的身份信息。在实际落地时我通常建议先接入一两个使用频率最高、改造成本最低的系统做试点比如内部 Wiki 或报表平台跑通后再推广到更多系统。一次接入所有系统风险太高出了问题定位也困难。4. 常见问题与排查技巧实录4.1 授权页报错“redirect_uri不匹配”这是见到最多的问题。钉钉开放平台对回调地址的校验非常严格必须是完整域名加具体路径且与创建应用时填写的地址逐字符匹配。常见的坑有两个。第一个是协议不一致钉钉后台填了https但 Hadess 配置导出的回调地址是http导致校验失败。确认 Nginx 是否已配置 HTTPS以及 Hadess 的发行者地址是否也用了https。第二个是地址路径不一致比如钉钉后台填了带尾部斜杠的地址但 Hadess 生成的回调地址没有尾部斜杠也会报不匹配。遇到这个报错时最直接的办法是把报错信息里带出的回调地址复制到 Notepad 里和钉钉后台配置的地址逐字对比。别凭感觉直接比较字符串最快。4.2 回调成功但用户信息拉取失败授权回调正常说明应用凭证和回调基本没问题。但回调成功后如果报“获取用户信息失败”问题大概率出在权限点没开通上。钉钉开放平台的权限点是按调用接口维度管理的只勾了扫码登录权限不等于就有权限读取手机号和个人邮箱。返回钉钉开放平台进入应用详情 - 权限管理搜索“个人手机号信息”“个人邮箱信息”“企业员工个人信息”等权限点确认已添加并发布。值得留意的是权限点修改后通常需要等待几分钟才会生效测试时别太急着下结论。4.3 扫码后提示“企业不存在或已被删除”这个报错通常和回调地址无关而是钉钉应用没有与企业完成授权绑定。企业内部应用创建后默认归属创建者所在的企业但如果创建者同时在多个组织中切换应用可能被关联到了错误的组织或者应用在某个组织中被停用了。处理办法是回到钉钉开放平台查看应用详情里的“所属企业”是否正确并在应用发布的组织范围内确认当前测试账号在该组织内且状态正常。如果企业内部组织较多优先用企业管理员账号操作避免跨组织数据隔离带来的混乱。4.4 登录态失效频繁Hadess 登录态失效通常与会话过期时间和钉钉侧令牌有效期有关。Hadess 的会话默认有较长的有效期但钉钉返回的访问令牌可能只有 2 小时甚至更短。如果用户在使用过程中频繁被要求重新扫码检查是否有定时任务在刷新令牌后没有同步更新 Hadess 侧的会话状态。另外一些业务系统自身也有会话有效期。用户通过了 Hadess 认证但业务系统的 session 过期了也会被引导重新走一次认证流程。这种情况不算 bug但可以通过调整业务系统的会话超时时间来优化体验。我在配置时的一般经验是Hadess 会话时间稍长比如 12 小时各业务系统接受 Hadess 签发的登录态并保持自己的会话与 Hadess 大体同步避免“每隔十分钟就跳一次登录”的尴尬。4.5 组织架构同步不及时钉钉集成之后员工入职、转岗、离职信息能否及时同步直接关系到权限管理的安全性。Hadess 通常支持两种同步策略实时拉取和定时同步。实时拉取指用户每次登录时实时请求钉钉接口获取最新资料保证单一用户信息始终是最新的。定时同步指每隔一段时间定时任务批量拉取企业组织架构和成员列表用于批量创建用户或更新部门关系。生产环境建议两者结合登录时实时拉取个人资料每天凌晨定时同步全量组织架构。如果发现离职员工仍然可以访问系统优先排查定时同步任务是否正常运行。身份认证平台里“账号能登录”不是最可怕的“员工离职了还能登录”才是大问题。宁可同步频率高一点、接口调用多一点也要保证离职员工及时失去访问权限。5. 最后再分享一点个人体会整套 Hadess 加钉钉集成的方案我从搭建到全量推开大概用了两周时间。第一周主要是部署和踩坑第二周就是逐步接入业务系统。最明显的感受是身份认证这种基础设施前期设计比后期补救重要得多。字段映射、回调地址、权限点是三个最关键的动作任何一个在前期没做对后期都会被反复折磨。如果你所在的公司还在用“每个系统一套账号”的原始方式我建议你尽快找一个内部系统试点接入。不用一开始就追求全套方案先用 Hadess 把钉钉登录跑通再在一个低频内部系统上接入验证慢慢扩展辐射范围。统一认证这件事越早做积累的技术债就越少。最后一个小技巧在把钉钉连接器配置完成后立刻导出配置备份包括回调地址、字段映射规则、连接器参数。我自己就遇到过版本升级后连接器配置被重置的情况如果没有备份重新配置一遍真的会让人心态崩溃。备份文件不用放在复杂的地方存到一个相对安全的内部文档里就够了关键时候能救命。
