3.2 KiB
3.2 KiB
5.2 认证与授权流程
:::tip 概述 登录是项目里最完整的业务链路:验证码 → 定位用户 → 状态校验 → 密码比对 → 签发双令牌 → 登计日志与在线会话。本页拆解每个环节与授权侧的角色权限装配。 :::
登录七步(service.Auth.Login)
1. 图形验证码 提供 key 时强制校验,一码一用(防重放爆破);未提供 key 跳过
2. 定位用户 用户名在租户内唯一;req.TenantCode 留空时全局定位(优先平台租户)
3. 账号状态 status 非 1 一律视为禁用
4. 租户校验 租户摘要(缓存 60 秒):禁用拒绝、过期拒绝;tenantID=0 平台级直通
5. 密码校验 外部 salt + bcrypt(password+salt);salt 为空直接比对
6. 签发双令牌 access/refresh 各带独立 jti
7. 登记 登录日志(gin_login_log)+ 在线会话缓存(允许多端并存)
任一环节失败返回对应业务错误码(CodeCaptchaError / CodeUserNotFound / CodeTenantNotFound / CodeUserDisabled / CodeTenantDisabled / CodeTenantExpired / CodePasswordWrong),除令牌签发失败直接上抛外,其余失败均写 status=1 的失败日志。
登录链路无事务:各环节是独立读/写,失败不产生半状态。
中间件接线
auth 模块在 init 中完成两处接线,供中间件回调:
middleware.SetIdentityLoader(...) // JWT 中间件拉取角色/权限(缓存 300 秒)
middleware.SetTenantLoader(...) // 租户中间件校验状态/过期(摘要缓存 60 秒)
未接线由 WireCheck 告警,中间件降级(身份扩展为空 / 租户校验跳过)。
授权:从菜单到接口
gin_menu(permission 节点)──勾选──▶ gin_role_menu
gin_role(data_scope 档位)──▶ gin_user_role ──▶ 用户
│
▼ LoadIdentity(登录后装配,缓存 300 秒)
角色编码集合 + 权限节点集合 + 数据范围(多角色取最宽松)
│
▼ 请求期
Authz:HasPerm(路由 Permission) → 超管直通 / 集合命中放行
DataScope:按档位在 applyFilters 链追加行级条件
令牌刷新(POST /api/oauth2/token,公开接口)
携带 refresh_token 兑换 → 校验类型与黑名单 → 签发新令牌对
旧 refresh 拉黑(防重放)→ 返回新 access/refresh
强制下线(DELETE /api/oauth2/remove/:token)
管理员在在线用户页对指定会话强制下线:拉黑该会话 access + refresh、移除在线登记。受保护接口,需要相应权限节点。
登出(GET /api/logout)
按在线登记复用同一拉黑逻辑(同时拉黑双令牌),移除在线登记并写登出日志。上下文缺 jti 时仅记日志,不视为错误。
排查建议
| 现象 | 检查 |
|---|---|
| 登录一直验证码错误 | 验证码 300 秒过期且一码一用;开发可配 bypassCode |
| Token 合法但 401 | 是否在黑名单(刚登出/被强退);jti 缓存键 |
| 有 Token 但接口 403 | 角色是否授权该权限码(见 5.4 权限管理) |
| 新授权不生效 | 权限缓存 300 秒,重新登录立即生效 |