1. 文档定位
本文说明 DGJ2.0 浏览器、PC 客户端、App、PDA、商城 Web 的登录与账号安全链路。重点不是“输入用户名密码”这一小段,而是登录请求经过账号状态、站点端开关、密码兼容、异地验证、设备绑定、客户端版本、授权次数、Session、单设备挤下线和强制重登的完整决策过程。
本文也区分“登录认证”和“业务权限”:登录成功只证明身份和端能力可用,菜单、资源、数据权限仍由第 19 篇权限体系继续判断。
2. 业务边界
2.1 包含
- Web、PC、App、PDA、商城 Web 五种登录类型。
- 密码、短信验证码、一键登录、静默登录和内部 token。
- 登录频率和每日错误次数限制。
- PC 机器码、版本、客户端形态、授权次数、绑定/解绑申请。
- App 设备记录和账号挤下线。
- Session 建立、检查、销毁和强制重登标记。
- 服务站 PC/App/PDA/商城/快小九/机器人开关。
- 财务锁定、OPS 配置、缓存失效和安全日志。
- 忘记密码和短信重置。
2.2 不包含
- 菜单、按钮、接口资源和数据权限,见第 19 篇。
- 总分店身份切换和总部账号业务,见第 36 篇。
- PDA 仓储作业,见第 26 篇。
- 支付、银行卡、用户实名认证和风控授信。
3. 五种登录类型
LoginType:
| 类型 | 值 | 入口/Service | 附加门槛 |
|---|---|---|---|
| 浏览器 Web | Dgjweb | passport/Login::signIn -> DgjwebSer | 账号、密码、端开关 |
| PC 客户端 | Dgjpc | pcSignIn -> DgjpcSer | token、机器码、版本、授权、异地验证 |
| App | Dgjapp | App Login -> DgjappSer | 设备、短信/一键、单设备登录 |
| PDA | Dgjpda | pda/User -> DgjpdaSer | PDA 开关、MD5 密码、24h Session |
| 商城 Web | Kzmallweb | KzmallwebSer | 商城开关、外部 TokenProvider |
flowchart LR
R[登录请求] --> F[UserFactory]
F --> W[DgjwebSer]
F --> P[DgjpcSer]
F --> A[DgjappSer]
F --> D[DgjpdaSer]
F --> K[KzmallwebSer]
W --> S[CI Session]
P --> S
A --> S
D --> S
K --> T[商城 Token]
4. 参与对象
| 对象 | 关键标识 | 作用 |
|---|---|---|
| 用户账号 | uid、username、sid、roleid | 身份和所属站点 |
| 服务站 | sid | 登录开关、区域、主账号 |
| PC 机器 | machine_code/c | 设备绑定与授权 |
| PC 版本 | v/version_id | 客户端包和升级 |
| 客户端形态 | client | 老单机/新单机/集成/体验/Tauri |
| App 设备 | device | 单设备登录和挤下线 |
| Session | session ID | 登录上下文 |
| 安全配置 | 端关闭字段 | 是否允许各端登录 |
5. 入口地图
5.1 Passport Controller
| 方法 | 作用 | 主要输入 |
|---|---|---|
checkSession | 检查 Web Session | Cookie/Session |
signIn | 浏览器登录 | 用户名、密码、token 等 |
silentSignIn | 按 sid 静默登录 | sid、入口鉴权 |
pcSignIn | PC 客户端登录 | 用户名、密码、机器码、版本、client |
pcSmsSend | 绑定/授权短信 | sid、业务类型 |
pcActiveBind | 短信主动绑定 | sid、机器码、验证码 |
pcGrantAuth | 短信增加/授权机器 | sid、验证码 |
pcBindApply | 提交绑定申请 | 机器码、sid |
pcUnbind | 提交解绑申请 | 机器码 |
signOut | 销毁 Session | 当前 Session |
getLoginedMobile | 忘记密码预检查 | username |
sendSmsCode | 重置密码短信 | mobile |
resetUserPassword | 重置主账号密码 | 手机号、验证码、新密码 |
5.2 其他入口
| 端 | Controller/Service |
|---|---|
| App | application/controllers/app/passport/Login.php、DgjappSer |
| PDA | application/controllers/pda/User.php、Pda/UserSer 或 DgjpdaSer 历史入口 |
| 账号安全 | application/Services/Safe/AccountSafeSer.php |
| PC 管理 | application/Services/Pc/* |
| 安全日志 | AccountSafeLogSer、tasks/AccountSafeLog.php |
6. 核心表
| 表 | 关键键 | 作用 |
|---|---|---|
t_sys_admin | uid、username、sid | DGJ 用户账号 |
t_sys_admin_config | sid + uid | 员工账号扩展配置 |
t_app_device | uid + device | App 设备登录记录 |
t_sys_pc_auths | sid、授权码 | PC 可绑定数量和有效期 |
t_sys_pc_versions | 版本号 | PC 版本、下载地址、上线状态 |
t_sys_pc_machines | machine_code + sid | 机器与站点绑定 |
t_sys_pc_login_control | sid | PC 登录控制 |
t_sys_pc_upgrade_log | 版本、机器 | PC 升级审计 |
t_sys_pc_bind_apply | 机器码、sid | 绑定申请 |
t_sys_pc_unbind_apply | 机器码 | 解绑申请 |
t_sys_ops_menu_rule 相关 | sid | 各端关闭开关 |
t_bs_account_safe_log | sid、操作人 | 账号安全配置日志 |
7. Redis 与 Session
| Key/机制 | 作用 |
|---|---|
ci_session:%s | 用户 CI Session |
dgj:rateLimit:login* | 60 秒登录频率 |
dgj:login.limit.{username}.{date} | 每日密码错误计数,达到阈值短时限制 |
HASH_PC_STATION_STATUS | PC 端开关缓存 |
HASH_APP_STATION_STATUS | App 端开关缓存 |
HASH_PDA_STATION_STATUS | PDA 端开关缓存 |
HASH_KZMALLWEB_STATION_STATUS | 商城 Web 开关缓存 |
HASH_RE_LOGIN | App/PDA 用户强制重登标记 |
REMOTE_LOGIN_WHITE_LIST | 异地登录豁免站点 |
app_mobile_login_tmp:* | App 手机号选站一次性凭证 |
USER_RIGHTS | 登录后业务权限缓存,不是认证状态 |
8. 通用登录门面
UserFactory(type) 动态实例化 App\Services\User\{type}Ser。
sequenceDiagram
participant C as Login Controller
participant F as UserFactory
participant L as 具体登录Service
participant Log as login_log
C->>F: login(type, params)
F->>F: 获取真实IP/用户名
F->>F: 60秒最多6次
F->>L: login(params)
L-->>F: status/msg/data
F->>Log: IP、端、结果、sid、uid、machine
F-->>C: 统一登录结果
9. 两层频控
9.1 UserFactory 频控
同登录名 60 秒允许 6 次(代码注释写 5 次,配置为 [60 => 6])。超过返回“登录频率过快”。
9.2 Passport 密码错误限制
startLogin 使用:
dgj:login.limit.{username}.{YYYYMMDD}
失败时自增并设置 300 秒过期,达到 10 次拒绝。由于每次失败都重新 expire(300),更接近“最后一次失败后 5 分钟”。Key 名含日期但 TTL 只有 5 分钟。
10. Web 登录
flowchart TD
A[signIn] --> B[beforeLogin清洗参数]
B --> C{记住密码?}
C -- 是 --> D[用户名和密码写Cookie]
C -- 否 --> E[清空Cookie]
D --> F[UserFactory Dgjweb]
E --> F
F --> G{账号/密码/开关通过?}
G -- 否 --> X[错误计数+失败日志]
G -- 是 --> H{首次登录?}
H -- 是 --> I[返回首次登录,不建正式Session]
H -- 否 --> J[saveSession]
J --> K[桌面首页]
beforeLogin 会在“记住密码”时将 userpwd 写 Cookie,保存时长 3,600,000 秒。客户端存明文密码属于高风险历史实现,应改为不可逆登录凭证或浏览器密码管理器,且 Cookie 必须 Secure/HttpOnly/SameSite。
11. Web Session 内容
saveSession 写 jxcsys:
| 字段 | 含义 |
|---|---|
uid/sid | 用户和服务站 |
name/username | 显示和登录账号 |
login | 固定 kzmall 历史值 |
areaCode/province/eparchy/city | 区域上下文 |
needChangePwd | 是否强制改密 |
roleid | 主/子账号角色 |
headOfficeAccount | 可选总部账号上下文 |
Session 是后续业务注入 JXCSID/JXCUID 的来源。禁止前端直接传 SID 覆盖 Session 真值。
12. 首次登录
当前特殊规则:
- 非生产环境强制
is_first_login = 0。 - 来源 IP 等于硬编码内网地址时跳过首次登录。
- 子账号
roleid != 0跳过首次登录。 - 主账号首次登录时可能不立即保存 Session,由前端引导安全步骤。
硬编码 IP 和环境分支必须在部署文档中登记,避免迁移后绕过或误拦。
13. 静默登录
silentSignIn(sid) 调 DgjwebSer::silentLogin 后直接保存 Session。它是高权限旁路:
- 必须由可信 OPS/内部入口调用。
- 必须记录原操作人、目标
sid和原因。 - 不能只依赖可猜的
sid。 - 切回原身份时应销毁目标 Session。
14. PC 请求字段
{
"username": "USER_DEMO",
"userpwd": "******",
"token": "PAGE_NONCE",
"c": "MACHINE_CODE_DEMO",
"v": "VERSION_NUMBER",
"client": 5
}
| 字段 | 作用 |
|---|---|
token | 页面/请求防伪 token;内部服务走 InnerTokenAuth |
c | 机器码 |
v | PC 软件版本号 |
client | 客户端形态枚举 1-5 |
15. PC 客户端类型
| 值 | 名称 |
|---|---|
1 | 老单机版 |
2 | 新单机版 |
3 | 集成版 |
4 | 最新体验版 |
5 | Tauri 版 |
DgjpcSer::checkPcLogin 首先要求 client 存在于该映射。增加新客户端必须同步登录校验、机器表、升级策略和统计页面。
16. PC 登录决策树
flowchart TD
A[PC登录] --> B{请求token有效?}
B -- 否 --> X[拒绝]
B -- 是 --> C{用户名密码机器码版本client齐全?}
C -- 否 --> X
C -- 是 --> D[查普通账号或总部账号]
D --> E{账号正常?}
E -- 否 --> X
E -- 是 --> F{站点PC开关正常?}
F -- 否 --> X
F -- 是 --> G{内部服务请求?}
G -- 是 --> H[InnerTokenAuth验证]
G -- 否 --> I[SMH加密或MD5密码兼容]
I --> J{需要异地登录验证?}
J -- 是 --> K[IP/设备/短信验证]
J -- 否 --> L[机器码与版本校验]
K --> L
H --> L
L --> M{绑定/授权通过?}
M -- 否 --> N[返回绑定/授权动作数据]
M -- 是 --> O[构建登录数据和Session]
17. PC 账号与密码
- 先按用户名/手机号查普通账号。
- 未找到时查询总部账号。
status必须正常。- 有
sid时检查 PC 站点开关缓存。 - 内部服务请求用
InnerTokenAuth校验传入userpwd。 - 普通请求兼容
encrypt(...,'SMH')和md5(password)两种历史密码。
密码迁移必须覆盖两种历史格式,不能只改一个端。
18. 异地登录
非首次登录、非内部服务、生产环境、站点不在白名单时可能调用 DgjCommonSer::checkRemoteLogin。LoginOptionEnums::REMOTE_LOGIN_CHECK = false 与实际分支/其他配置的关系需确认。
校验通常依赖 IP、机器和短信。排查异地登录失败时同时查:
- 真实客户端 IP 是否被代理覆盖。
- 白名单 Redis。
- 主/子账号分支。
- 短信手机号和验证码。
- 客户端机器码是否变化。
19. PC 机器码自动记录
checkPcLogin 查不到机器码时,会先调用 addMachinesCode(sid, code, version) 记录机器。机器记录存在不等于已授权;还要看状态、SID 绑定和规则开关。
机器表需要区分:
- 物理机器码。
- 关联站点。
- 版本 ID。
- 客户端形态。
- 状态/软删。
- 使用信息和错误说明。
20. PC 登录规则开关
Redis HASH_ZGJ_PC_RULE_LOGIN[sid] 为真时,服务站必须遵守机器绑定/授权规则。白名单旧逻辑已注释。
规则关闭时仍可能记录机器码,但不按严格绑定拦截。排查“同机器某站可登、某站不可登”应先查站点规则。
21. PC 授权次数
t_sys_pc_auths 保存站点授权:
| 字段语义 | 说明 |
|---|---|
num | 可授权总数 |
use_num | 已使用数量 |
over_time | 过期时间 |
auth_code | 授权批次/码 |
AuthsModel::findAvailableOneBySid 用于新机器判断。授权不足、过期或已用完时返回绑定/申请流程,而不是建立 Session。
22. PC 绑定方式
22.1 主动短信绑定
sequenceDiagram
participant U as 用户
participant C as Login Controller
participant S as BindSer
participant SMS as 短信
participant DB as PC Tables
U->>C: pcSmsSend(sid,bizType=1)
C->>SMS: 绑定服务站验证码
U->>C: pcActiveBind(sid,c,sms_code)
C->>S: activeBind
S->>SMS: 校验验证码
S->>DB: 机器与站点绑定/关闭申请
22.2 绑定申请
pcBindApply(c,sid) 写绑定申请,等待后台审核后 BindSer::bind 建立关系。
22.3 授权机器码
pcGrantAuth(sid,smsCode) 用“授权机器码”短信业务处理授权,不应与绑定站点验证码混用。
23. PC 解绑
用户 pcUnbind(c) 先写解绑申请。后台通过 UnbindSer::unbind:
- 若指定
sid,软删该机器与站点关系。 - 未指定时可能软删机器全部关系。
- 关闭同机器解绑申请。
stateDiagram-v2
[*] --> 未绑定
未绑定 --> 绑定申请中: pcBindApply
未绑定 --> 已绑定: 短信主动绑定
绑定申请中 --> 已绑定: 后台bind
已绑定 --> 解绑申请中: pcUnbind
解绑申请中 --> 未绑定: 后台unbind
已绑定 --> 禁用: MachinesSer reversal
禁用 --> 已绑定: reversal
24. PC 版本
VersionsSer 支持新增、列表和设为上线;MachinesSer 支持按地区/站点更新版本、查询升级、版本反查站点和升级日志。
| 关系 | 说明 |
|---|---|
版本号 -> version_id | 登录时映射 |
| 机器 -> 版本 ID | 当前/目标版本关系 |
| 版本上线状态 | 当前可用包 |
| 升级日志 | 操作人、机器集合、版本和参数 |
未知版本在某些调用 throwEnable=false 时可能记录 version_id=0;严格登录路径是否拒绝需按 afterLogin 继续核对。
25. App 登录方式
App 支持:
- 账号密码。
- 手机短信验证码。
- 运营商一键登录
accessToken。 - 一个手机号关联多个站点时,先返回可选站点,再用临时 token 选账号。
flowchart TD
A[App手机登录] --> B{one_click还是sms_code}
B -- one_click --> C[OneClickLoginProvider换手机号]
B -- sms_code --> D[SmsProvider校验验证码]
C --> E[按手机号查在职员工和有效账号]
D --> E
E --> F{只有一个有效账号?}
F -- 是 --> G[直接构建登录数据]
F -- 否 --> H[生成app_mobile_login_tmp临时凭证]
H --> I[用户选择站点/账号]
I --> J[校验临时凭证并立即删除]
J --> G
26. App 手机号选站
有效账号条件包含:
- 员工未删除。
- 手机号匹配。
- 员工未禁用且在职。
- 已绑定
adminAccount。 SYS_ADMIN未删除、状态启用。
临时 token 读取手机号后,在成功选站时立即删除,防止重放。需确认 TTL、随机强度和是否绑定设备/IP。
27. App 单设备登录
DgjappSer::add_device(device, uid):
- 将该 UID 所有设备记录置
isDelete=1并写登出时间。 - 查当前
uid + device历史记录。 - 不存在则新增。
- 存在且已退出则恢复
isDelete=0并写登录时间。
sequenceDiagram
participant N as 新设备
participant S as DgjappSer
participant DB as APP_DEVICE
N->>S: 登录(uid,deviceB)
S->>DB: uid全部设备isDelete=1/logout_time
S->>DB: 查uid+deviceB
alt 首次设备
S->>DB: INSERT deviceB active
else 历史设备
S->>DB: UPDATE deviceB active
end
接口鉴权层必须在每次请求检查当前设备是否仍 active,否则“记录挤下线”不会真正阻止旧 Session 使用。
28. App 短信和一键频控
| 动作 | Key | 限制 |
|---|---|---|
| 手机登录 | 手机或设备 MD5 | 60 秒 6 次 |
| 发送登录验证码 | 手机号 | 60 秒 1 次 |
短信 Provider 以 uid 校验验证码;手机号绑定多个账号时使用首个有效 UID 作为校验主体,选站后再绑定具体账号。
29. PDA 登录
DgjpdaSer:
- 校验用户名和密码非空。
- 查询正常用户。
- 检查 PDA 站点开关缓存。
- 检查账号状态。
- 仅兼容
md5(password)。 - 读取站点系统信息构造个人/公司资料。
- 写区域 Cookie。
- 清除 UID 的 PDA 强制重登标记。
Pda/UserSer 登录成功后将 Session 失效设置为 86400 秒,并返回 sessionId。
flowchart LR
A[PDA账号密码] --> B[账号状态]
B --> C[PDA站点开关]
C --> D[MD5密码]
D --> E[公司/个人资料]
E --> F[清PDA强制重登]
F --> G[24h Session]
30. 站点端开关
AccountSafeSer 从 OPS 菜单规则配置读取:
| 字段 | 控制端 |
|---|---|
is_close_pc | PC |
is_close_app | App |
is_close_pda | PDA |
is_close_kzamll_web | 商城 Web |
is_close_sass | 快小九/SAAS |
is_close_robot | 机器人 |
配置值 1 表示关闭,0 表示开启;登录缓存返回值 1 表示正常、2 表示不正常。两套 1/0/2 语义不能混用。
31. 端开关缓存
sequenceDiagram
participant L as 登录Service
participant R as Redis
participant DB as OpsMenuRule
L->>R: hGet(key,status)
alt 缓存命中
R-->>L: 1正常或2关闭
else 未命中
L->>DB: 查询is_close_xxx
DB-->>L: 0/1
L->>R: 写1或2
L-->>L: 返回登录状态
end
setAccountConfig 更新数据库后调用 unsetStatusCache(sid) 删除 PC/App/PDA 缓存;商城缓存由专用方法删除。新增端开关必须同步缓存失效。
32. 设置账号安全配置
setAccountConfig(sid, accountConfig, apiUser):
- 读取新旧 PC/App/PDA/SAAS/机器人开关。
- 快小九或机器人一旦关闭,当前代码不允许再次开启。
- 关闭 SAAS 时发送 MQ 解绑服务站客户并退出登录。
- 关闭机器人时删除该站客户群 ID。
- 保存操作人姓名和编码。
- 删除端开关缓存。
- 若 PC/App/PDA 全关,将站点主账号状态改为删除/禁用。
- 任一端开启时,将主账号恢复正常。
33. 关闭不可逆分支
当前代码:
is_close_sass从 1 改 0:抛“快小九账号关闭,无法再次开启”。is_close_robot从 1 改 0:抛“机器人账号已关闭,无法再次开启”。
这不是普通开关,而是含解绑/清群的不可逆业务操作。页面必须二次确认,并展示影响范围;恢复只能走专门的重新开通流程。
34. 全端关闭与账号状态
flowchart TD
A[更新PC/App/PDA开关] --> B{三端都关闭?}
B -- 是 --> C[主账号status=DELETED/0]
B -- 否 --> D{任一端开启?}
D -- 是 --> E[roleid=0主账号status=NORMAL/1]
C --> F[清端缓存]
E --> F
端开关和账号状态是两层。解开一个端时会恢复主账号,但子账号状态如何恢复需单独确认。
35. 强制重新登录
HASH_RE_LOGIN 按设备类型建 Hash:
- App 类型
1 - PDA 类型
2
setNeedReLogin(uid) 同时给 App 和 PDA 写标记;登录成功分别 clearReLogin。业务请求中必须调用 needReLogin 才能真正拦截旧会话。
stateDiagram-v2
[*] --> 正常会话
正常会话 --> 必须重登: setNeedReLogin(uid)
必须重登 --> 登录页: 请求中检测needReLogin
登录页 --> 正常会话: 新登录clearReLogin
36. 财务锁定
lockPdaAndApp(sid):
- 关闭 App、PDA、商城 Web。
- 操作人写“财务”。
- 清 App/PDA/商城缓存。
- 调用
TokenProvider::dgjAccountLoginOut退出该站所有商城账号。
unLockPdaAndApp 恢复三个开关并清缓存。它不直接清每个用户的 CI Session,旧 Session 的失效依赖各端请求校验。
37. 忘记密码流程
sequenceDiagram
participant U as 用户
participant C as Login Controller
participant S as LoginService
participant R as Redis
participant SMS as SmsProvider
U->>C: getLoginedMobile(username)
C->>S: verifyUser
S->>S: 仅roleid=0主账号可重置
C->>R: mobile -> uid, 带TTL
C-->>U: 脱敏手机号
U->>C: sendSmsCode(mobile)
C->>SMS: sendVerifier(uid,mobile)
U->>C: resetUserPassword(mobile,code,password)
C->>SMS: match(uid,code)
C->>S: 更新密码
38. 重置密码边界
- 子账号
roleid != 0不允许该流程。 - 用户名查询后将
mobile -> uid临时写 Redis。 - 发送短信又按手机号查用户,需防同手机号多账号歧义。
- 短信开关关闭时发送接口直接返回成功,重置接口是否仍校验需联调。
resetUserPassword接收的 password 是否已在 Controller 加密需核对后半段代码,禁止存明文。- 改密后应给该 UID 设置强制重登并撤销所有旧 Session/设备 token。
39. Session 生命周期
| 端 | 建立 | 检查 | 销毁/失效 |
|---|---|---|---|
| Web/PC | saveSession | checkSession/login_session | signOut sess_destroy |
| App | 登录 Service +设备记录 | API Session/设备 active/重登标记 | 设备挤下线、Session 过期 |
| PDA | Pda/UserSer | PDA API Session | 24h、重登标记 |
| 商城 | TokenProvider | 商城 token | dgjAccountLoginOut |
CI Session 配置来自环境 session.php。生产 Cookie 的 Secure、HttpOnly、SameSite、域、IP 匹配和 ID 重生成必须以部署配置确认。
40. 登录日志
UserFactory::addLoginLog 写 login_log:
| 字段 | 内容 |
|---|---|
ip | 真实 IP |
channel | 登录类型 |
params | 请求 JSON |
status | 结果 |
sid/uid | 成功上下文 |
mac | PC 机器码 |
当前直接 json_encode($params) 可能把密码、验证码、accessToken 和临时 token 写日志;内部服务还单独写 auth_token。这是高风险敏感日志问题,应在日志入口统一脱敏或字段白名单。
41. 账号安全日志
t_bs_account_safe_log 和 AccountSafeLogSer 用于记录 OPS/财务配置变更;初始化任务补历史日志。至少应记录:
sid- 变更前后开关
- 操作人/来源
- 时间和原因
- 是否触发 SAAS 解绑、机器人清群、商城登出
- 执行结果和失败步骤
42. PC 数据关系
erDiagram
SYS_ADMIN ||--o{ PC_MACHINE : logs_in
STATION ||--o{ PC_AUTH : owns
STATION ||--o{ PC_MACHINE : binds
PC_VERSION ||--o{ PC_MACHINE : installed
PC_MACHINE ||--o{ BIND_APPLY : applies
PC_MACHINE ||--o{ UNBIND_APPLY : applies
PC_VERSION ||--o{ UPGRADE_LOG : target
43. 登录数据流
flowchart LR
I[用户名/手机/验证码] --> A[身份校验]
A --> B[账号状态]
B --> C[站点端开关]
C --> D[设备/机器/版本]
D --> E[异地/短信/一键]
E --> F[构建sid/uid/role/区域]
F --> G[Session/Token]
G --> H[菜单和业务权限]
44. 状态矩阵
| 状态层 | 正常 | 异常 | 处理 |
|---|---|---|---|
| 用户账号 | status=1 | 0/其他 | 拒绝登录 |
| 站点端开关 | DB is_close=0 | 1 | 拒绝该端 |
| 缓存登录状态 | 1 | 2 | 拒绝该端 |
| 机器绑定 | active | 未绑定/禁用 | 绑定、申请或拒绝 |
| 授权 | 有剩余且未过期 | 用完/过期 | 申请授权 |
| App 设备 | isDelete=0 | 1 | 旧设备退出 |
| 强制重登 | 无 Hash 字段 | 有字段 | 返回登录页 |
| Session | 有效 | 过期/销毁 | 重新登录 |
45. 典型失败:密码正确仍不能登录
flowchart TD
A[密码正确仍失败] --> B{登录频率/错误次数?}
B -- 超限 --> C[等待TTL/查Redis]
B -- 正常 --> D{账号status正常?}
D -- 否 --> E[查账号/全端关闭]
D -- 是 --> F{该端开关正常?}
F -- 否 --> G[查AccountSafe配置和缓存]
F -- 是 --> H{PC?}
H -- 是 --> I[机器码/版本/client/授权/异地]
H -- 否 --> J{App/PDA?}
J -- 是 --> K[设备/重登/短信/Session]
46. 典型失败:PC 提示绑定/授权
排查顺序:
client是否在 1-5。v是否能映射版本。- 机器码是否存在、是否软删、是否禁用。
- 机器码是否绑定当前
sid,而不是只绑定其他站。 - 站点是否启用严格 PC 登录规则。
AuthsModel::findAvailableOneBySid是否有剩余授权和有效期。- 是否已有绑定/解绑申请未关闭。
- 短信验证码业务类型是否正确。
47. 典型失败:修改开关不生效
| 检查 | 预期 |
|---|---|
| DB 配置 | is_close_xxx 已更新 |
| Redis | 对应端状态 Key 已删除 |
| 下次登录 | 回源 DB 并写 1/2 |
| 已登录请求 | 每次请求仍校验开关/重登 |
| 商城 | 外部 token 已登出 |
| SAAS | 解绑 MQ 已成功消费 |
| 机器人 | 群 ID 已清除 |
48. 典型失败:App 旧设备仍可用
- 查
t_app_device是否旧设备已isDelete=1。 - 查新设备是否 active。
- 查 API 中间件是否每次核对设备。
- 查旧 CI Session 是否仍有效。
- 查
needReLogin(uid, APP)。 - 查客户端是否缓存离线数据而误以为在线。
49. 只读 SQL:账号
SELECT uid, sid, username, mobile, roleid, status, isDelete,
is_first_login, needChangePwd, create_time, modify_time
FROM t_sys_admin
WHERE username = 'USER_DEMO' OR uid = 10001;
禁止查询或导出密码字段到工单和文档。
50. 只读 SQL:PC 机器与授权
SELECT id, sid, machine_code, status, version_id, client_version,
is_delete, use_info, error, create_time
FROM t_sys_pc_machines
WHERE machine_code = 'MACHINE_DEMO'
ORDER BY id;
SELECT id, sid, num, use_num, over_time, introduction, create_time
FROM t_sys_pc_auths
WHERE sid = 20001
ORDER BY id DESC;
SELECT id, number, name, status, url, create_time
FROM t_sys_pc_versions
WHERE id IN (
SELECT version_id FROM t_sys_pc_machines WHERE machine_code = 'MACHINE_DEMO'
);
51. 只读 SQL:申请和设备
SELECT * FROM t_sys_pc_bind_apply
WHERE machine_code = 'MACHINE_DEMO'
ORDER BY id DESC;
SELECT * FROM t_sys_pc_unbind_apply
WHERE machine_code = 'MACHINE_DEMO'
ORDER BY id DESC;
SELECT id, uid, device, isDelete, login_time, logout_time
FROM t_app_device
WHERE uid = 10001
ORDER BY login_time DESC;
52. Redis 只读排查
生产使用项目受控工具,不使用广域 KEYS:
GET dgj:login.limit.USER_DEMO.20260716
HGET <PC_STATUS_KEY_FOR_SID> status
HGET <APP_STATUS_KEY_FOR_SID> status
HGET <PDA_STATUS_KEY_FOR_SID> status
HGET <RE_LOGIN_APP_HASH> 10001
HGET <RE_LOGIN_PDA_HASH> 10001
真实前缀和格式由 RedisKeys 与环境前缀共同决定。
53. 代码定位
rg -n "function (signIn|pcSignIn|silentSignIn|signOut|resetUserPassword)" \
application/controllers/passport/Login.php
rg -n "class UserFactory|RateLimit|addLoginLog|mobileLogin" application/Services/UserFactory.php
rg -n "checkPcLogin|addMachinesCode|afterLogin|REMOTE_LOGIN" \
application/Services/User/DgjpcSer.php
rg -n "add_device|mobileLoginSelectStation|sendMobileLoginSmsCode" \
application/Services/User/DgjappSer.php
rg -n "LoginStatusCache|setAccountConfig|needReLogin|lockPdaAndApp" \
application/Services/Safe/AccountSafeSer.php
rg -n "class (BindSer|UnbindSer|AuthsSer|MachinesSer|VersionsSer)" application/Services/Pc
54. 安全问题清单
| 风险 | 当前证据 | 建议 |
|---|---|---|
| 明文密码 Cookie | beforeLogin 写 userpwd | 移除,改短期设备凭证 |
| MD5 历史密码 | PC/PDA/轮胎等 | 渐进迁移 Argon2/bcrypt |
| 登录日志保存请求 | params=json_encode | 白名单+脱敏 |
| 内部 auth token 日志 | auth_token 字段 | 禁止持久化明文 |
| Session 固定 | 需查生产配置 | 登录成功重生成 ID |
| 静默登录 | 按 SID | 强认证+审计+短时权限 |
| 设备挤下线 | 只更新设备表 | 中间件每请求校验 |
| 多状态语义 | 0/1/2 混用 | 强类型枚举和值对象 |
55. 补偿 SOP:机器绑定错站
- 导出机器全部 SID 关系、状态、版本和申请。
- 确认物理机器所有人和目标站点。
- 关闭未处理的相反申请。
- 使用
UnbindSer软删错误关系,不物理删历史。 - 使用正常绑定流程关联目标站点。
- 验证授权次数、机器登录和旧站不可登录。
56. 补偿 SOP:端开关缓存错
- 查 DB 真值和修改日志。
- 删除单个 SID 对应端缓存,不做全库清理。
- 重新调用只读状态接口让缓存回源。
- 验证新登录和已有会话。
- 若数据库被错误修改,走审计审批恢复,而不是只改 Redis。
57. 补偿 SOP:改密后旧会话仍有效
- 确认密码已按正确格式落库。
setNeedReLogin(uid)标记 App/PDA。- 销毁/撤销 Web/PC Session。
- 将 App 设备全部置退出,要求新设备重新登录。
- 调用商城 Token 登出。
- 验证旧 Cookie、Session ID、设备和商城 token 全失效。
58. 禁止动作
- 在日志、群聊、文档打印密码、验证码、accessToken、内部 token。
- 直接把账号状态改 1 绕过端关闭原因。
- 只删除 Redis 缓存当成永久解锁。
- 物理删除机器、绑定和安全日志。
- 未确认设备归属就跨站绑定机器码。
- 为恢复机器人/SAAS 直接把不可逆开关改回 0。
- 修改 Session 数据伪造
sid/uid/roleid。
59. 监控建议
| 指标 | 维度 | 告警 |
|---|---|---|
| 登录成功率 | 端、版本、地区 | 显著下降 |
| 失败原因 | 密码/状态/开关/机器/验证码 | 异常集中 |
| 登录频控触发 | 用户/IP/设备 | 暴力尝试 |
| 异地验证量 | 地区、站点 | 突增 |
| 机器绑定/解绑失败 | 机器、站点 | 连续失败 |
| 授权用尽站点 | SID | 提前预警 |
| App 设备挤下线 | UID | 异常频繁 |
| 强制重登未执行 | UID/端 | 超 SLA |
| 安全开关变更 | 操作人/端 | 全量审计 |
| 敏感字段日志命中 | 日志源 | 任一命中 |
60. 回归清单:Web 与密码
- [ ] 正确/错误用户名密码。
- [ ] 用户名和手机号登录。
- [ ] SMH/MD5 历史密码。
- [ ] 账号禁用、临时关闭、全端关闭。
- [ ] 60 秒频控和错误 10 次限制。
- [ ] 首次登录、子账号、非生产和内网特殊分支。
- [ ] 记住密码 Cookie 移除/兼容。
- [ ] Session ID 重生成、检查和退出。
- [ ] 静默登录权限和审计。
- [ ] 忘记密码主账号、子账号、短信失败、验证码错误。
- [ ] 改密后所有旧会话失效。
61. 回归清单:PC
- [ ] 缺少 token/机器码/版本/client。
- [ ] client 1-5 和非法值。
- [ ] 普通账号与总部账号。
- [ ] PC 端开关和缓存。
- [ ] 严格规则开启/关闭。
- [ ] 新机器首次记录。
- [ ] 机器绑定当前站、其他站、禁用、软删。
- [ ] 授权足够、用尽、过期。
- [ ] 主动短信绑定和后台绑定申请。
- [ ] 授权短信业务类型。
- [ ] 解绑申请、单站解绑和全机器解绑。
- [ ] 异地登录白名单、短信和 IP。
- [ ] 版本不存在、升级和回退。
- [ ] 并发登录同一机器/同一站点。
62. 回归清单:App、PDA 与安全开关
- [ ] App 账号密码、短信、一键登录。
- [ ] 手机号无账号、单账号、多站点选站。
- [ ] 临时 token 过期、重复和跨设备。
- [ ] 发送短信 60 秒频控。
- [ ] App 新设备登录挤下旧设备。
- [ ] 旧设备 API 请求被拒绝。
- [ ] PDA 正确/错误 MD5 密码。
- [ ] PDA 24 小时 Session。
- [ ] App/PDA 强制重登标记和清除。
- [ ] PC/App/PDA 单独关闭和组合关闭。
- [ ] 三端全关禁用主账号,重新开一端恢复。
- [ ] 财务锁定/解锁和商城登出。
- [ ] SAAS 关闭解绑 MQ,不可逆重开。
- [ ] 机器人关闭清群,不可逆重开。
- [ ] 配置变更缓存失效和安全日志。
63. 改动风险
| 级别 | 代码/行为 | 最低回归 |
|---|---|---|
| P0 | UserFactory、Session、密码验证 | 全端登录和旧密码迁移 |
| P0 | AccountSafeSer 开关/全端关闭 | 全端、账号状态、SAAS/机器人副作用 |
| P0 | 设备挤下线/强制重登中间件 | App/PDA 所有受保护 API |
| P1 | DgjpcSer 机器/版本/授权 | 全 PC 客户端和绑定流程 |
| P1 | 忘记密码/短信/一键登录 | 频控、重放、多账号、安全 |
| P1 | 登录日志 | 可观测性和敏感字段 |
| P2 | 登录页、背景图、提示文案 | 各端兼容和错误码 |
64. 已确认事实
UserFactory按类型路由登录,并统一限流和写登录日志。- Passport 有额外每日用户名错误计数限制。
- Web Session 保存 UID、SID、角色、区域等上下文。
- PC 必填 token、机器码、版本和客户端类型。
- PC 密码兼容 SMH 和 MD5,内部请求用
InnerTokenAuth。 - PC 客户端类型有 1-5 五种。
- PC 严格规则开启时检查机器绑定和授权。
- App 支持短信/一键登录和多站点选择。
- App 登录会将同 UID 其他设备置退出。
- PDA 检查独立端开关并清强制重登标记。
- 端关闭配置用 0/1,缓存登录状态用 1/2。
- 强制重登分别按 App/PDA Hash 保存。
- 财务锁定会关闭 App/PDA/商城并登出商城 token。
- SAAS/机器人关闭带不可逆副作用。
65. 待确认与缺口
- Web/PC/App/PDA 实际路由和中间件全集。
- 生产 Session Cookie 安全配置和存储驱动。
REMOTE_LOGIN_CHECK=false与实际异地校验分支关系。- PC
afterLogin机器授权所有返回码和状态。 - PC 表唯一索引、授权并发扣减和机器码稳定性。
- App 设备 active 是否在每个请求强校验。
- 强制重登是否覆盖所有 App/PDA API。
- 手机号多账号短信验证 UID 选择规则。
- 重置密码最终存储格式和旧会话撤销。
- 安全日志真实字段、保留期和告警。
- 登录日志是否已在采集层脱敏。
- SAAS 解绑 MQ 重试、机器人群 ID 恢复流程。
66. 证据来源
application/controllers/passport/Login.phpapplication/controllers/app/passport/Login.phpapplication/controllers/pda/User.phpapplication/Services/UserFactory.phpapplication/Services/User/DgjwebSer.phpapplication/Services/User/DgjpcSer.phpapplication/Services/User/DgjappSer.phpapplication/Services/User/DgjpdaSer.phpapplication/Services/User/KzmallwebSer.phpapplication/Services/Passport/LoginService.phpapplication/Services/Safe/AccountSafeSer.phpapplication/Services/Safe/AccountSafeLogSer.phpapplication/Services/Pc/*application/models/pc/*application/KzData/Enums/LoginType.phpapplication/KzData/Enums/LoginOptionEnums.phpapplication/KzData/Enums/StationEnums.phpapplication/KzData/Enums/RedisKeys.phpapplication/config/tables.phpapplication/config/session.php(环境文件)
67. 一页式交接结论
- 登录成功需要依次通过身份、账号状态、端开关、设备/机器、版本/授权和 Session。
- Web、PC、App、PDA、商城不是同一套附加规则,排障先确定登录类型。
- PC 的机器存在不等于已绑定,绑定不等于有授权,版本正确也不等于端开关正常。
- App 单设备登录只有在 API 每次检查设备 active 时才真正有效。
- 强制重登是 UID+端 Redis 标记,与站点端关闭缓存不是一回事。
- 账号安全 DB 用 0/1,登录缓存用 1/2,不能直接比较。
- 三端全关会禁用主账号,重新开任一端会恢复主账号。
- SAAS 和机器人关闭包含解绑/清群,是不可逆业务动作。
- 明文密码 Cookie、MD5、请求日志敏感字段和静默登录是当前高风险点。
- 改密、锁站和设备切换都必须验证旧 Session、旧设备、商城 token 真正失效。
请求-日志-数据变更追踪卡
多入口请求链路
| 场景 | 调用方与入口 | 请求载荷/上下文 | Controller/Consumer | Service/Provider | 汇合点 | 最终业务事实 |
|---|---|---|---|---|---|---|
| Web/PC 登录 | /passport/Login、PC 登录 | 账号、密码/验证码、设备、IP | Passport Controller | UserFactory、DgjwebSer/DgjpcSer | user/admin ID + session | 建立登录会话和站点权限 |
| App/PDA 登录 | /app/passport/Login、pda/User | 手机/账号、设备 ID、版本、验证码 | App/PDA Controller | User/Safe Service | user + device | token/session 与设备绑定 |
| 改密/重登 | 安全中心/管理员操作 | 用户、旧新凭证、强制重登标记 | Account Controller | AccountSafeSer | user ID | 密码更新,旧凭证失效 |
| 锁站/PC 授权 | OPS/PC 管理 | sid、终端类型、设备/白名单 | 管理入口 | PC/Safe Service | station+terminal/device | Redis 开关/授权决定是否允许登录 |
日志证据矩阵
| 链路段 | 日志来源 | 可检索锚点 | 成功信号 | 失败信号 | 与下一段关联方式 | | --- | --- | --- | --- | --- | --- | --- | | 登录请求 | Login Controller | request_id、账号 hash/用户 ID、sid、设备 ID、IP | 认证成功并生成 session/token | 密码/验证码错、锁定、站点禁用 | 用户 ID 进入权限/设备校验 | | 设备/站点校验 | Safe/PC Service | user、device、terminal、Redis key | 命中授权或白名单 | 设备冲突、终端状态关闭 | station+terminal key 回查 Redis | | 会话建立 | User Service/session/token | session/token ID(日志仅 hash)、user ID | 新会话可访问受权接口 | 会话未保存、上下文 sid 错 | 会话 ID 关联后续 request ID | | 失效操作 | AccountSafeSer | user ID、action、HASH_RE_LOGIN | 旧 session/token/设备请求均拒绝 | 只改密码未清旧会话 | 用户/设备逐端验证 |
环节数据变更台账
| 步骤 | 代码位置 | 事务 | 读取事实 | 写入表/缓存/MQ | 字段或数量变化 | 回查证据 |
|---|---|---|---|---|---|---|
| 查账号 | Login/UserFactory | 只读 | 用户状态、站点、密码 hash、权限 | 无 | 零写入;日志不得出现明文密码/token | user/admin ID、状态 |
| 校验终端 | PC/Safe Service | 只读 Redis | HASH_*_STATION_STATUS、设备/白名单 | 无 | allow/deny 计算 | sid+terminal+device |
| 建会话 | Dgjweb/Dgjpc/App/PDA Service | 登录事务/缓存写 | 用户权限和站点 | session/token、设备关系、登录时间 | 新 session/token insert;last_login old -> now | token hash、设备、登录时间 |
| 改密/强退 | AccountSafeSer | 用户事务 + 缓存清理 | 当前凭证和活跃会话 | 用户表、HASH_RE_LOGIN、session/token 缓存 | password hash 更新;版本/重登标记 +1;旧会话删除/拒绝 | 各终端旧凭证回归 |
| 权限加载 | BaseController/USER_RIGHTS | 只读/缓存 | user role、SYS_ADMIN、资源关系 | session rights/cache | DB 不变;请求上下文获得权限 | 最小/管理员账号对照 |
子模块追踪:login-web Web 登录与 Session
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 登录 | 浏览器提交账号凭证 | request ID、account hash、client/session ID | application/controllers/passport/Login.php -> application/Services/Passport/LoginService.php | 密码 hash、账号/站点状态、登录类型和终端开关 | 登录本地事务/缓存写 session none -> active、last_login old -> now | request ID + admin/user ID + client type | 失败零业务写入;日志不含明文密码/token |
| 会话校验 | 后续 Web 请求 | session hash、user/sid | application/Services/User/DgjwebSer.php | session、重登版本、账号和权限状态 | 校验查询只读;过期/失效删除或拒绝 session | request ID + session hash + user/sid | Session 有但账号已锁仍拒绝;重新登录而非手改缓存 |
子模块追踪:login-first-silent 首次登录与静默登录
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 首次登录 | 新账号首次进入 | user ID、first-login flag、client | application/Services/UserFactory.php | 账号初始化、密码/协议/选站要求 | 用户本地事务 first_login true -> false 或保持待完成;session 按规则建立 | request ID + user + option/status | 必做步骤未完成不得绕过;失败不清除首次标记 |
| 静默登录 | 有效旧凭证自动续会话 | token/session hash、device、relogin version | application/KzData/Enums/LoginOptionEnums.php | token、设备、账号和强退标记 | 缓存事务外续期 old expiry -> new,业务 DB 不变 | request ID + token hash + device | 强退/改密后静默登录必须失败;旧 token 不恢复 |
子模块追踪:login-pc PC 登录与客户端类型
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| PC 登录 | PC 客户端账号登录 | account、client type/version、machine code | application/Services/User/DgjpcSer.php -> application/KzData/Enums/LoginType.php | 账号、PC 开关、机器授权和客户端类型 | 登录本地事务/缓存建 PC session,登录时间更新 | request ID + user/sid + client/machine | Web/PC 类型不可混用;未授权设备零业务写入 |
| 类型回查 | 登录成功但菜单/行为错误 | session、login type、user rights | application/Services/UserFactory.php | 实际 Service、客户端类型和权限缓存 | 查询只读 不写 | request ID + service/type + rights count | 修正路由/类型后重登,不直接篡改 session 字段 |
子模块追踪:pc-bind PC 机器码绑定、授权与解绑
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 绑定授权 | 管理员/用户绑定 PC 机器码 | user/sid、machine hash、action | application/Services/User/DgjpcSer.php | 原绑定、设备上限、白名单和操作权限 | 设备本地事务 unbound -> bound/authorized,写操作时间 | request ID + user/sid + machine hash | 同设备/超上限按规则拒绝;机器码只记录 hash |
| 解绑强退 | 解绑或撤销授权 | relation ID、machine hash | application/Services/Safe/AccountSafeSer.php | 绑定关系和该设备活跃 session | 本地事务 bound -> unbound;commit 后清 PC session | request ID + relation + cleared sessions | 清缓存失败只补强退,不恢复绑定关系 |
子模块追踪:login-app App 登录、选站与单设备
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 登录选站 | App 登录/选择服务站 | user、device ID、target sid、token | application/controllers/app/passport/Login.php -> application/Services/User/DgjappSer.php | 用户可用站点、App 开关、单设备规则和旧 token | 登录本地事务/缓存 token old -> new、currentSid 更新,旧设备失效 | request ID + user/device + sid + token hash | target sid 无权零写入;不记录真实 token |
| 单设备验收 | 第二台设备登录或旧设备访问 | user、two device IDs、relogin version | application/Services/Safe/AccountSafeLogSer.php | 活跃 token、设备关系和安全日志 | 新登录使旧 token active -> invalid | user + device hashes + login times | 旧设备必须拒绝;缓存失败补清旧 token |
子模块追踪:login-pda PDA 登录
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| PDA 登录 | 仓内设备登录 | user、device、sid、warehouse | application/controllers/pda/User.php -> application/Services/User/DgjpdaSer.php | PDA 开关、用户仓库权限、账号/设备状态 | 登录本地事务/缓存建 PDA session none -> active | request ID + user/sid + device/warehouse | PC/App token 不可复用;无仓库权限零写入 |
| 作业校验 | PDA 后续扫码请求 | session hash、billNo、location | application/Services/User/DgjpdaSer.php | session、当前站点/仓库和重登标记 | 鉴权查询只读 不写 | request ID + session hash + billNo | session 失效时业务动作不得部分执行 |
子模块追踪:terminal-switch 站点端开关与缓存
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 配置开关 | OPS 开停 Web/PC/App/PDA | sid、terminal type、status、operator | application/KzData/Enums/StationEnums.php | 原端状态、白名单和站点状态 | 配置本地事务/缓存 terminal old -> enabled/disabled | request ID + sid + terminal + status | 禁用后新登录必须拒绝;已登录是否强退按规则处理 |
| 缓存回查 | DB 已改但登录结果旧 | sid、HASH_*_STATION_STATUS key | application/KzData/Enums/RedisKeys.php | DB 配置、Redis 值和更新时间 | 事务外 cache old -> latest/deleted,DB 不变 | sid + key + hit/value version | 只清目标站点终端键;Redis 环境事实待验证 |
子模块追踪:account-security 账号安全配置与强制重登
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 安全配置 | 修改安全策略/账号状态 | user/sid、policy/action、operator | application/Services/Safe/AccountSafeSer.php | 原策略、账号、活跃会话和操作权限 | 用户本地事务 security/status old -> new、relogin version +1 | request ID + user/sid + action/version | 无权操作零写入;安全日志不存凭证明文 |
| 全端强退 | 锁定、改密等触发 | user、session/token keys | application/Services/Safe/AccountSafeLogSer.php | Web/PC/App/PDA 活跃凭证 | commit 后事务外删除/拒绝所有端凭证 | user + cleared key counts + client types | 部分清理失败按用户重试;不回滚已生效安全状态 |
子模块追踪:password-reset 忘记密码与重置
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 验证重置 | 忘记密码验证码/管理员重置 | user/mobile hash、verify request、operator | application/Services/Passport/LoginService.php | 账号、验证码/权限、密码策略和重放标记 | 用户本地事务 password hash old -> new、relogin version +1 | request ID + user + reset type + result | 验证失败零写入;不记录验证码和新密码 |
| 旧会话失效 | 重置成功后 | user、all client sessions | application/Services/Safe/AccountSafeSer.php | 活跃凭证和最新重登版本 | commit 后清缓存,旧 session/token active -> invalid | user + client/session counts | 清理失败继续拒绝旧版本并补删缓存 |
子模块追踪:finance-lock 财务锁站与全端失效
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 锁站 | 逾期/财务规则触发 | sid、repayment/lock ID、reason | application/Services/Safe/AccountSafeSer.php | 所有有效锁因、站点状态和现有会话 | 站点本地事务 unlocked -> locked;commit 后全端凭证失效 | task/request ID + sid + lock reasons + cleared counts | 多锁因分别保留;锁站失败不应允许新资金动作 |
| 解锁 | 全部锁因解除 | sid、remaining lock IDs | application/KzData/Enums/AccountEnums.php | 逾期/黑名单最终事实和当前锁态 | 条件满足才本地事务 locked -> unlocked,用户需重新登录 | sid + resolved/remaining reasons | 不恢复旧 token;缓存菜单/终端状态另行刷新 |