第03篇已经明确了整体服务划分和核心链路。本篇先聚焦认证中心这一段:用户登录成功后,如何创建TGT并进入后续流程。
不管走OAuth2还是CAS ST,用户都要先在base-oauth2登录页完成身份认证。真正麻烦的地方不是JDBC查询本身,而是邮箱、工号、钉钉扫码三个入口,最终都要映射到umd_user里的同一个用户主体;同时还要处理验证码校验、登录频率限制以及历史密码迁移。OAuth2授权码回调、网关换JWT、服务注册JSON,分别留给第05、06篇;这里不展开。
认证段在整体链路中的位置
链路A和链路B在创建TGT之前共用同一套登录逻辑:用户打开登录页 → 提交表单 → base-oauth2完成JDBC认证 → 创建TGT写入Redis。之后链路A走OAuth2授权码,链路B签发ST给第三方应用。 
三种登录方式,如何最终落到同一个用户
登录页通过CAS WebFlow的自定义字段customFields[loginType]区分三种入口,对应枚举LoginTypeEnum:
| pc | 企业邮箱 | 是 | GET /center/base-umd/user/detail/email/{email} | 优先工号,无工号回退邮箱 | 是 |
| pcWorkCode | 工号 | 是 | 否 | 工号 | 是 |
| pcDingQrCode | 钉钉扫码 | 否 | GET /center/base-umd/user/detail/ding/scan/{code} | 优先工号,无工号回退邮箱 | 跳过 |
表单还携带customFields[captchaCode]。CAS配置里把loginType和captchaCode注册为必填自定义字段:
cas:
view:
customLoginFormFields:
captchaCode:
required: true
loginType:
required: true
登录页三个Tab分别提交不同表单:工号Tab带loginType=pcWorkCode;邮箱Tab拼接企业邮箱后缀后带loginType=pc;钉钉Tab扫码成功后自动提交,loginType=pcDingQrCode,password字段填占位值non(钉钉不走密码校验)。
Principal用工号还是邮箱,我们在第02篇PRD里定过规则:有工号用工号,没有才回退邮箱。三种入口在Helper阶段就把username改写成同一套规则,后面JDBC和Principal收集不用再分岔。
以后加新登录方式,在CustomJdbcAuthenticationHelper增加分支,登录页加Tab即可,不用改JDBC Handler主体。这是有意把「入口差异」和「查库认证」拆开,避免Handler越改越乱。
为什么需要在CAS JDBC认证前增加一层Helper
CAS自带的QueryDatabaseAuthenticationHandler只负责JDBC查库和密码比对,它不知道邮箱后缀、钉钉临时code、图形验证码这些事。如果在Handler里硬塞loginType分支,以后每加一种登录方式都要动核心认证类,测试面也会越来越大。
所以我们在认证入口之前增加一层CustomJdbcAuthenticationHelper,专门处理三件事:根据loginType分流、校验验证码,以及调用base-umd将邮箱或钉钉code转换成后续JDBC认证使用的username。
从credential.getCustomFields()读取loginType,默认按邮箱登录处理:
// com.column.sso.auth.CustomJdbcAuthenticationHelper
public LoginTypeEnum preprocess(UsernamePasswordCredential credential) {
Object loginType = credential.getCustomFields().get(\”loginType\”);
LoginTypeEnum type = LoginTypeEnum.PC;
if (\”pcWorkCode\”.equals(loginType)) {
type = LoginTypeEnum.PC_WORK_CODE;
} else if (\”pcDingQrCode\”.equals(loginType)) {
type = LoginTypeEnum.PC_DING_QR_CODE;
}
if (type == LoginTypeEnum.PC) {
网硕互联帮助中心




评论前必须登录!
注册