跳转至

Signon 模块 API

Signon 模块是 MyApps 平台的**认证与单点登录服务**(obpm-signon),提供账号密码登录、SSO(CAS / OIDC)登录、微信/钉钉扫码登录、短信验证码登录与注册、代理用户登录、自动登录、企业域列表查询、accessToken 换取与刷新、用户注销等认证域能力。该模块默认运行在 8085 端口,context-path 占位符为 ${myapps.context-path.signon:}(部署时替换为具体上下文路径,缺省为空;lite 统一打包下为 /,此时模块路径前缀多一层 /signon)。

注:本模块控制器**不共享统一的 /api/rest 前缀**。类级 @RequestMapping 仅绑定 context-path 占位符,方法级路径各自独立(/conn_test//api/login/.../api/runtime/login/.../api/domains/api/refreshAccessToken/api/logout.action/api/open-applogout/sso)。顶层 index.md「服务与基址」表中 signon 行所列 /api/rest 仅为占位,实际基址以本文档与各控制器文档为准。

覆盖进度:3 / 3 控制器(已覆盖 LoginController、JumpToController、LogoutController)

Signon 模块共有 3 个有端点的控制器,合计 27 个端点(登录 25 + 跳转 1 + 注销 1)。源码树中另有 ContextPathController/runtime/consul/contextpath,仅用于服务发现查询 runtime 的 contextPath,归入运维/服务发现范畴,不在本认证域文档范围内)不单独成文。

已文档化控制器

文件 中文名 基址 端点数
login.md LoginController(登录控制器) ${myapps.context-path.signon:} 25
jump-to.md JumpToController(跳转控制器) ${myapps.context-path.signon:} 1
logout.md LogoutController(注销控制器) ${myapps.context-path.signon:} 1

鉴权说明

(据源码)Signon 是**认证服务本身**,其设计前提是「在用户取得令牌之前为其服务」,因此**模块内不存在任何强制校验 accessToken/adminToken 的过滤器或拦截器**——这与 runtime(RestSecurityHandlerInterceptor)、message(MessageSecurityFilter)、manager(ManagerSecurityFilter)有本质区别。具体过滤链如下。

启动器与组件扫描

启动类 cn.myapps.run.Signon2App(consul / eureka / nacos 三个 profile 与 war 打包同名启动器):

@SpringBootApplication
@ComponentScan(basePackages = {"cn.myapps.*.conf", "cn.myapps"})

cn.myapps.*.conf 覆盖 cn.myapps.common.conf.CommWebMvcConfig(obpm-common),由此注册共享过滤器;cn.myapps 覆盖 cn.myapps.signon.conf.SignonMvcConfig,注册 CAS 相关过滤器。

过滤器链(按 order 排列)

order 过滤器 来源 作用
HIGHEST_PRECEDENCE PassFilter(匿名内联 Filter obpm-common CommWebMvcConfig.filterRegistrationBeanPassFilter1 命中白名单 URL 即标记 request.setAttribute("pass", true) 并放行,不参与鉴权
-1 CommonSecurityFilter obpm-common CommWebMvcConfig.filterRegistrationBeanCommonSecurityFilter1(URL 模式 /* 系统间调用鉴权与 HTTP 方法收敛
1 HiddenHttpMethodFilter obpm-common CommWebMvcConfig 允许 POST 表单隐藏 PUT/DELETE
2 OBPMAuthenticationFilter(CAS) signon SignonMvcConfig.casAuthenticationFilter **仅当 authentication.type=ssosso.implementationCasUserSSO 时**重定向到 CAS 登录页;其余情况直接放行
3 OBPMCas20ProxyReceivingTicketValidationFilter(CAS) signon SignonMvcConfig.casTicketValidationFilter CAS 票据校验,仅 SSO+CAS 模式下生效

signon 不使用 Spring Security(全模块无 org.springframework.security 引用),不注册任何 HandlerInterceptor

CommonSecurityFilter 行为(据 cn.myapps.common.web.CommonSecurityFilter

  1. 系统间调用放行:携带合法 systemToken 请求头(Security.verifySystemToken,JWT 内 username 固定为 systemToken)→ 标记 pass=true 放行。
  2. HTTP 方法收敛:仅允许 GET/POST/HEAD/OPTIONS,其他方法返回 HTTP 405(HTML 错误页)。OPTIONS 为浏览器 CORS 预检放行。
  3. 系统未就绪Environment.isReady() 为 false 时返回 HTTP 500,响应体「系统正在启动中,请稍后再试!」。
  4. 文档/监控页保护/v3/api-docs/swagger-ui/druid 须持有效 designerToken 或 adminToken;/actuator/health 放开;其余 /actuator/** 返回 401(无响应体)。
  5. 其他请求:直接 chain.doFilter不校验业务 token

PassFilter 白名单(与 signon 相关条目)

CommWebMvcConfig.filterRegistrationBeanPassFilter1 硬编码(无配置入口),命中即 pass=true

  • 模块首页://signon/manager/manager//designer/designer/
  • 登录页面/signon/*/api/runtime/login/*/api/authtime/login/*/api/designtime/login/*(lite 下另有 /manager/api/authtime/login/*/designer/api/designtime/login/*/obpm/api/runtime/login/*
  • 调试/移动端登录/api/debuglogin/*/api/login/*/runtime/app/security/*/obpm/runtime/app/security/*
  • 注销/api/runtime/logout/runtime/logout/api/authtime/logout/api/designtime/logout
  • runtime 取 token:/api/rest/accessToken/rest/accessToken/api/runtime/secrets/*
  • 健康检查:/health/actuator/health/kms/health/ai/health
  • 静态资源后缀:.jpg .js .css .ico .png .gif .html .json .map .woff2 .woff .ttf .eot .svg .mpg .mp4 .mp3 .wav .avi .flv .m3u8 .m3 .ts
  • magic-api:/magic-api/*/obpm/magic-api/*

signon 大部分端点位于 /api/runtime/login/**全部落在白名单内/api/login/exchangeAccessToken/api/domains/api/refreshAccessToken/api/logout.action/api/open-app/conn_test/logout/sso 不在白名单,但因 CommonSecurityFilter 不做 token 校验,仍可匿名访问

CAS 单点登录(可选)

当部署方配置 authentication.type=ssosso.implementationCasUserSSO 时,OBPMAuthenticationFilter 会对未持有 CAS 断言(session 内 CONST_CAS_ASSERTION)的请求重定向到 CAS 登录页;其中 /actuator/health 与匹配 logout.action 的 URI 直接放行,微信浏览器(User-Agent 含 MicroMessenger)也直接放行。OIDC(OidcSSO)与微信/钉钉扫码登录走控制器内的 LoginController 逻辑,不经 CAS 过滤器。

执行用户

signon 控制器**不通过过滤器注入执行用户**。需要识别用户的端点在控制器内自行解析:

  • Cookie checkInTokensignIngetUserDomains 从该 cookie 取中间令牌(Security.getUserIdFromToken,60 秒有效期,由 checkin 端点签发),缺失返回「登录已失效,请重新登录」。
  • Cookie 自动登录票据autologin 通过 CookieAuthValidator.valid(request, response) 校验。
  • 请求内 accessTokenrefreshAccessToken 调用 Security.getUserIdFromToken(request),按 query 参数 accessToken → query access_token → 请求头 accessToken → Cookie accessTokenAuthorization: Bearer <token> 顺序解析。
  • 路径变量 / 业务参数getProxyUsersloginProxyexchangeAccessToken 等以业务参数(用户 id、域名)定位用户,不依赖请求级鉴权。

完整鉴权机制与错误码说明见:顶层 index.md

响应结构与错误码

Signon 模块控制器返回**多种响应形态**(按控制器 / 方法区分),不全部采用顶层统一 Resource

形态一:Resource(统一响应)

LogoutController 使用。由 new Resource(0, errmsg, data, null) 构造,与顶层 index.md「统一响应结构」一致:

{ "errcode": 0, "errmsg": "ok", "data": "<注销重定向 URL>", "errors": null }

形态二:result(...) 自定义包装(LoginController 多数端点)

LoginController.result(resultCode, msg, dataName, data, ...) 构造,序列化为 JSON:

{
  "resultCode": "0|1|7|400",
  "msg": "<描述>",
  "<dataName>": <data>,
  ["<dataName2>": <data2>],
  ["<dataName3>": <data3>]
}
字段 类型 说明
resultCode string 业务码:"1"=成功,"0"=失败/通用错误,"7"=密码已过期,"400"=参数/校验错误
msg string 描述信息
其他键 任意 动态数据键(如 accessTokenreturnUrldomainscheckcodecheckcodeImgtimeouturlmultiLangWordListresultproxyUsers),具体见各端点

该形态**与顶层统一 Resource 不同**——字段名是 resultCode/msg 而非 errcode/errmsg

形态三:success/error 自定义包装(LoginController getDomains

{ "status": 0, "message": "ok", "data": [<Domain>...] }
字段 类型 说明
status int 0=成功(错误时也为 0,错误信息走 message/data
message string "ok""error"
data object/null 业务数据

形态四:原始 JSON / HTML 字符串

  • 原始 JSONObjectgetWxConfiggetDdConfiggetSessionKey 直接返回 JSONObject,无外层包装。
  • HTML/JS 字符串test/conn_test)、doIndexPage/)、doSSOdologoutSSOwxQrCodeLoginddQrCodeLogin 通过 @ResponseBody 返回形如 <script>window.location='...'</script> 的 HTML,由浏览器执行跳转;登录成功者同时通过 Set-Cookie 下发 accessToken

错误码补充

Signon 模块**未引入模块专属业务错误码**(HTTP 层由 CommonSecurityFilter 统一处理)。鉴权 / 启动层引入以下与统一 Resource 不同的纯 HTTP 状态码:

errcode / resultCode HTTP 含义
405 405 HTTP 方法不被允许(由 CommonSecurityFilter 拦截,仅允许 GET/POST/HEAD/OPTIONS,返回 HTML 错误页)
500 500 系统正在启动中(CommonSecurityFilterEnvironment.isReady() 为 false 时返回,HTML 错误页)
401 401 访问 /actuator/**(除 /actuator/health 外)未授权;/v3/api-docs/swagger-ui/druid 未持有效 designerToken/adminToken 时返回提示页
resultCode "0" 200 业务失败(账号锁定、密码错误、验证码错误、用户不存在等,包在 result 自定义结构中)
resultCode "7" 200 密码已过期(包在 result 自定义结构中,附带 code 为重置用临时 token)
resultCode "400" 200 参数校验错误(如 exchangeAccessToken 未传 domainId/domainName,包在 result 自定义结构中)

覆盖说明

本阶段覆盖 obpm-signon 工作树下的 LoginController(登录控制器,25 个端点,含首页重定向、连接测试、checkin/signin 两步登录、SSO/CAS/OIDC 登录、微信/钉钉扫码登录回调、短信验证码登录与注册、代理用户登录、自动登录、企业域列表、多语言词列表、accessToken 换取与刷新、密码找回)、JumpToController(跳转控制器,1 个端点,写 cookie 后 JS 跳转至门户首页)、LogoutController(注销控制器,1 个端点,注销后返回重定向 URL)。除 ContextPathController(服务发现辅助,非认证域)外,Signon 模块有端点控制器已**全部覆盖**。