当标准 SSO(企业控制台配置)无法满足客户需求时,通过基于 Java 开发的独立 Jar 服务 proinnova-sso 实现定开单点登录,最终仍由用户中心完成 Cookie 写入与页面跳转。完整登录链路见 定开登录流程。
对接主要围绕五项工作展开:
配置 Jar 侧参数:在 application-*.properties 或业务模型表(business_table)中维护认证策略、第三方地址、验票参数等
配置 config.json:设置 environment: "OP"、OPLoginConfig 及登录页/中转规则
配置第三方入口与回调地址:统一入口 buildAuthUrl,以及 IdP 回调 /login 或 /login/do-redirect
准备用户数据:提前将可登录用户导入或同步到账户中心,保证第三方身份能映射到 DeepFOS 账号,且状态为 启用(勿触发激活邮件)
部署与联调 proinnova-sso Jar:OP 环境发布、Nginx 反代及端到端验证
此外,以下两项通常作为额外开发内容评估:
客户分支策略扩展改造:proinnova-sso 已内置 CAS、OAuth2、基于业务表的验票等策略;若现有策略或配置方式仍无法满足客户认证流程,可在 master 基础上按客户分支定开扩展(如新增认证驱动、调整验票或跳转逻辑)。
登录页第三方入口改造:若需在 /login 登录页直接展示第三方登录入口(如企微登录、微软登录等),需改造用户中心前端登录页(element-login)的页面与交互逻辑,而不仅是配置 proinnova-sso 参数。
仓库:proinnova-sso
产物:proinnova_sso.jar
对外路径前缀:/proinnova_sso/(Nginx 反代到 Jar 端口,如 8000)
认证策略(SSOStrategyEnum):当前已实现 CAS、OAUTH2、PASSWORD_FREE,以及基于业务表的 OAUTH2/CAS 等;若现有策略无法满足客户需求,可按枚举扩展新的认证驱动
分支与开发
定开 SSO 统一基于 master 分支开发与维护;新客户定开从 master 拉出客户分支(通常以客户编号命名)后按需扩展。
OP 发布要点(详见项目内 README.md)
Jar:spring.profiles.active 对应 application-{profile}.properties;启动参数 --seepln.account.server=用户中心域名
环境变量:ACCOUNT_SERVER 指向用户中心域名
Nginx:location /proinnova_sso/ { proxy_pass http://ip:port/proinnova_sso/; }
用户中心 config.json(非 Jar 内文件):运维在部署用户中心静态资源时覆盖;OP 定开需配置 environment: "OP" 与 OPLoginConfig
application-*.properties 与 business_table)proinnova-sso 的认证参数(协议类型、第三方地址、ClientId/Secret、buildAuthUrl 等)写在 Jar 配置或业务模型表中。需与 OPLoginApiUrl、state 及第三方地址等保持一致。
|
方式 |
适用场景 |
|
配置位置 |
|---|---|---|---|
|
properties 固定配置 |
OP 单客户、参数相对固定 |
|
|
|
business_table 业务表 |
SSO 参数维护在业务模型/清单表 |
|
业务模型元素 |
以客户编号为前缀,在 application-{profile}.properties 中维护,例如客户 xx:
# 基础
xx.base.env=op # op | saas
xx.base.domain=xx.com # 用户中心一级域名(Cookie 域)
xx.base.authStrategy=OAUTH2 # 对应 SSOStrategyEnum:CAS、OAUTH2 等
xx.base.buildAuthUrl=... # buildAuthUrl?state=xx 最终 302 到的第三方认证地址
xx.base.usernameTurnLowercaseFlag=1
# OAuth2
xx.oauth2.serverUrlPrefix=...
xx.oauth2.authenticationAccessTokenUrl=...
xx.oauth2.authenticationUserinfoUrl=...
xx.oauth2.clientId=...
xx.oauth2.clientSecret=...
xx.oauth2.redirectUri=... # 与 IdP 登记的回调地址一致,对齐用户中心 `/login` 或 `/login/do-redirect`
xx.base.oauth2UsernameNickname=... # 从第三方 userinfo JSON 取用户名的字段名
spring.profiles.active 决定加载哪个 application-{profile}.properties 文件
GET /proinnova_sso/user/buildAuthUrl?state=xx 时,读取 xx.base.buildAuthUrl
POST /proinnova_sso/user/getUserInfo 且 state=xx 时,读取 xx.base.authStrategy 选择验票驱动
当 state 含 ,business_table 时,不再读 {客户编号}.* 的 properties 节点,而是按 sso_code(逗号前一段)查询业务模型中的 SSO 配置。
配置要点:
导入元素包:先将 sso 文件夹(导出元素的文件包)导入应用的 /system/component/ 目录下
业务表:在业务模型中维护元素 sso_config(通过清单表与明细表维护),主键字段 sso_code 与 state 逗号前一段一致
主表字段(示例):env、domain、build_auth_url、auth_strategy、default_application_link 等
子表(明细表):按子表类型 OAUTH2 或 CAS 挂载对应明细字段(如 token_url、userinfo_url、client_id、service_validate_url 等,见仓库 BusinessSlaveConstant)
Jar 全局参数(仍在 application-*.properties):sys.app、sys.space、sys.folderId、sys.username,用于调用业务模型查询接口
策略:主表 auth_strategy 填 OAUTH2_BUSINESS_TABLE 或 CAS_BUSINESS_TABLE,分别走 OAUTH2DriverByDBImpl / CASDriverByDBImpl(与 properties 模式的 OAUTH2 / CAS 枚举值不同)
与前端、入口对齐:
config.json:OPLoginApiUrl 建议写为 /proinnova_sso/user/getUserInfo?state={sso_code},business_table
第三方入口:/proinnova_sso/user/buildAuthUrl?state={sso_code},business_table
验票成功后,proinnova-sso 通过配置项 seepln.account.sso.url(定义于 application-*.properties)调用账号中心完成平台登录。常见两个接口:
接口 1:POST /system-login-api/api/oauth/sso/login
配置示例:seepln.account.sso.url=${seepln.account.server}/system-login-api/api/oauth/sso/login
场景说明:master 默认,走账号中心标准 SSO 登录逻辑(在线人数、登录限制等策略)
参数表:
|
参数名 |
位置 |
必填 |
说明 |
|---|---|---|---|
|
|
body |
是 |
映射后的平台用户名,用于账号中心定位并生成平台登录态 |
接口 2:POST /system-login-api/api/oauth/sso/auth/login
配置示例:seepln.account.sso.url=${seepln.account.server}/system-login-api/api/oauth/sso/auth/login
场景说明:回调验证场景,账号中心可按配置对 accessToken 做回调校验后再签发登录态
参数表:
|
参数名 |
位置 |
必填 |
说明 |
|---|---|---|---|
|
|
body |
是 |
映射后的平台用户名,用于账号中心定位并生成平台登录态 |
|
|
body |
否 |
第三方 access token,用于账号中心侧回调校验 |
|
|
body |
否 |
透传扩展字段,供账号中心回调校验或定开扩展逻辑使用 |
account 服务环境变量
|
环境变量 |
说明 |
取值 / 行为 |
使用方 |
|---|---|---|---|
|
|
回调验证开关 |
|
|
|
|
登录回调验证地址 |
开启回调验证时,账号中心在处理 |
由账号中心调用; |
config.json 配置config.json 是用户中心前端的运行时配置,不是 proinnova-sso Jar 的 application-*.properties。定开 SSO 场景下,config.json 主要决定两件事:
用户访问 /、/login 时,是直接进入单点登录,还是展示登录页
第三方认证系统回调到用户中心后,前端最终把回调参数转发给哪个后端接口
|
路由 |
用途 |
说明 |
|---|---|---|
|
|
用户中心默认登录入口 |
当 |
|
|
强制显示登录页 |
可作为管理员登录入口;若超管开启“单点用户登录限制”,则单点用户只能通过 SSO 登录,不能通过登录页登录 |
|
|
定开 SSO 的显式单点登录回调页 |
当既要保留登录页登录、又要支持单点登录时,通常将第三方认证回调到这个地址 |
|
|
标准 SSO 回调页 |
供标准 SSO 使用,不建议用于 |
|
配置项 |
示例 |
说明 |
|---|---|---|
|
|
|
切换到 OP / 定开登录链路;若不是 |
|
|
|
决定访问 |
|
|
|
当 |
|
|
|
可选。中转或异常场景下,前端展示的自定义 HTML |
|
|
|
与标准 SSO 类似,开启后前端优先按后端返回的 |
只需要单点登录,不保留登录页登录
建议配置:
{
"environment": "OP",
"OPLoginConfig": {
"enabledRedirect": true,
"pageInnerHTML": "<p style='color:#f00'>自定义HTML</p>",
"OPLoginApiUrl": "/proinnova_sso/user/getUserInfo?state=xx"
},
"loginSetting": {
"enabledSystemRedirect": true
}
}
效果:
/、/login 直接进入单点登录中转,不展示普通登录页,并将回调参数转发给 OPLoginApiUrl
第三方认证回调地址:{用户中心域名}/login
既要单点登录,也要保留登录页登录
建议配置:
{
"environment": "OP",
"OPLoginConfig": {
"enabledRedirect": false,
"pageInnerHTML": "<p style='color:#f00'>自定义HTML</p>",
"OPLoginApiUrl": "/proinnova_sso/user/getUserInfo?state=xx"
},
"loginSetting": {
"enabledSystemRedirect": true
}
}
效果:
/login 展示普通登录页;/login/do-redirect 进入单点登录中转,并将回调参数转发给 OPLoginApiUrl
第三方认证回调地址:{用户中心域名}/login/do-redirect
定开 SSO 需要区分两类第三方侧地址,不能混用:
|
类型 |
配置地址 |
场景与说明 |
|---|---|---|
|
第三方可直接调用:统一入口地址 |
|
适用于门户、企微/钉钉菜单、浏览器书签等入口。平台按 |
|
第三方认证系统回调地址 |
|
认证系统登录成功后会直接回调到该地址;联调/排障时也可能人工直接访问。只需要单点登录(不保留登录页)时通常用 |
sequenceDiagram
participant User as 用户浏览器
participant IdP as 第三方认证系统
participant UC as 用户中心 element-login
participant SSO as proinnova-sso
participant AC as 账号中心
User->>SSO: 1. GET /proinnova_sso/user/buildAuthUrl?state=客户编号
SSO->>IdP: 2. 读取配置并 302 到第三方认证页
IdP->>UC: 3. 回调 /login 或 /login/do-redirect(携带 ticket/code/state)
UC->>SSO: 4. 前端中转页 POST OPLoginApiUrl(通常指向 /proinnova_sso/user/getUserInfo)
SSO->>IdP: 5. 验票 / 换 token / 取用户
SSO->>AC: 6. POST .../system-login-api/api/oauth/sso/login 或 auth/login
SSO->>UC: 7. Set-Cookie + 返回 redirect/html
UC->>User: 8. 跳转产品地址
流程拆解
外部入口发起认证:GET /proinnova_sso/user/buildAuthUrl
关键入参:state
state 两种常见格式:
固定配置模式:{客户编号}
业务模型表模式:{sso_code},business_table
proinnova-sso 按 state 读取配置后,直接 302 跳转到第三方认证页(buildAuthUrl)
IdP 认证后回调用户中心前端
回调地址二选一:
仅 SSO(不保留登录页):{用户中心域名}/login
SSO 与登录页并存:{用户中心域名}/login/do-redirect
回调参数通常在 query 中,核心为:
state(必传)
ticket(CAS)或 code(OAuth2)
用户中心前端中转到 proinnova-sso
常见中转路由:
/login:enabledRedirect=true 时直接进入中转
/login/do-redirect:显式中转页(常用于“保留登录页 + SSO 并存”)
前端中转页最终复用 redirect.tsx
当 environment="OP" 时,前端将回调 query 原样作为 body,POST 到 OPLoginConfig.OPLoginApiUrl(通常是 POST /proinnova_sso/user/getUserInfo)
proinnova-sso 验票并调用账号中心登录
驱动选择规则(POST /proinnova_sso/user/getUserInfo)
|
触发条件 |
使用的策略 |
|---|---|
|
body 含 |
|
|
|
由业务表 |
|
其他 |
读 |
按所选策略完成验票,并得到第三方用户标识
|
策略值 |
配置来源 |
驱动类 |
关键入参 |
说明 |
|---|---|---|---|---|
|
|
properties: |
|
|
调 CAS |
|
|
properties: |
|
|
|
|
|
不读 |
|
|
跳过第三方验票,直接以 body 中的 |
|
|
业务表: |
|
|
配置来自业务模型表 |
|
|
同上,主表 |
|
|
配置来自业务模型表 |
|
|
— |
— |
— |
枚举中已定义,当前未注册驱动;配置为 |
映射为 DeepFOS 登录用户名并调用账号中心
OAuth2/CAS 验票成功后得到第三方账号;若配置了 usernameTurnLowercaseFlag,用户名可能转小写
最终以映射后的用户名调用账号中心(accountUserInfo = AccountUtils.ssoLogin(...)):
默认:POST /system-login-api/api/oauth/sso/login(loginParam 为平台用户名)
回调验证场景:POST /system-login-api/api/oauth/sso/auth/login(除 loginParam 外可携带 token、extra_data)
写 Cookie 并完成前端跳转
登录成功后由 proinnova-sso 写入主域 Cookie(Driver 的 afterAdvice(...) 中调用 cookieDefend.setCookie(...))
返回 SSOResult(如 redirect / html / manualHandler)
用户中心前端根据返回值决定自动跳转或展示错误页(同标准 SSO)
定开通常围绕 POST /proinnova_sso/user/getUserInfo 开发,其中主要改造点通常是验票 / 换 token / 取用户相关逻辑;账号中心登录、写 Cookie、SSOResult 返回等环节一般可复用现有实现。若需要新增一种认证方式(新 Driver),建议按以下步骤实现:
接入策略并完成分发
在 SSOStrategyEnum 增加新的策略类型
新增 Driver:实现 AbstractSSODriver(或 AbstractSSOByDBDriver),参考 定开登录流程 与当前已实现的驱动类(如 CASDriverImpl、OAUTH2DriverImpl、PasswordFreeDriverImpl)进行开发
在 SSODriverFactory / SSOByDBDriverFactory 注册新 Driver
确认 LoginController.getUserInfo 能按 authStrategy(或 business_table)分发到该 Driver
新增 Driver(即 DriverImpl)必做事项(核心)
实现验票逻辑(对接第三方认证系统)
验票成功后,得到第三方用户标识(如用户名/工号/邮箱)
将该标识转换为平台登录入参(通常为 loginParam)
调用账号中心登录接口(/system-login-api/api/oauth/sso/login 或 auth/login,即 accountUserInfo = AccountUtils.ssoLogin(...))
登录成功后由 proinnova-sso 写入主域 Cookie(Driver 的 afterAdvice(...) 中调用 cookieDefend.setCookie(...))
最终由统一流程返回 SSOResult(如 redirect / html / manualHandler),供用户中心前端完成最终跳转或错误展示
异常约定
RedirectException:缺少必填票据(如 code/ticket)或需重新发起认证时抛出;返回中通常带 redirect,前端应跳转回 IdP
ValidationException:第三方验票失败、账号中心登录失败或关键参数异常时抛出;前端应展示 SSOResult.html(若有)并中止自动跳转
最小联调检查
配置一致性:state、回调 URL、authStrategy 与 Driver 注册保持一致
验票链路:第三方返回 code/ticket 后,/proinnova_sso/user/getUserInfo 能正确完成验票
账号中心登录:验票成功后可调用账号中心并签发登录态(Cookie 正常写入)
前端表现:前端可按 SSOResult 正常跳转;异常场景可展示错误页而非静默失败
当客户要求在 /login 登录页直接展示第三方入口(如企微登录、微软登录等)时,需要改造用户中心前端 element-login,不只依赖后端 SSO 参数。
两类改造方式(实施选择)
方式 A:直接改编译后登录页文件(在 /login 对应的前端静态页面 index.html 中,从指定位置贴入自定义代码)
优点:开发轻量,不需要新开前端项目
缺点:运维成本高,需要手工贴代码,发布流程长且容易失败
编译后的 index.html 结构示例(自定义入口代码通常贴在 <body> 内、<div id="root"></div> 前后,以运维/项目约定为准):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
<link rel="icon" href="/element-login/favicon.svg" type="image/x-icon" />
<title>登录</title>
<script type="module" crossorigin src="/element-login/assets/index-6ba900a9.js"></script>
<link rel="stylesheet" href="/element-login/assets/index-1e51a7c3.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
方式 B:起前端新项目(拉现有资源包,开发完整登录逻辑)
优点:运维更稳定,按服务部署即可,无需上线时手工改文件
缺点:开发成本高,接近完整前端项目改造
前端页面改造点(element-login)
在 /login 登录页增加第三方登录入口按钮/区域(文案、图标、点击事件)
点击后跳转到定开入口地址,建议使用:
/proinnova_sso/user/buildAuthUrl?state=xx
或 /proinnova_sso/user/buildAuthUrl?state={sso_code},business_table
在“登录页与 SSO 并存”场景下,可引导到 /login/do-redirect,该地址就是显式中转页
回到顶部
咨询热线
