外观
认证与登录
概述
认证与登录是系统管理(module_system)的入口模块,负责用户身份的认证、会话令牌的签发与刷新、第三方账号的接入,以及登录后权限信息的聚合下发。它向下依赖基础设施层的 JWT、Redis 会话、在线用户等能力,向上为前端登录页、单点授权页、社交绑定等场景提供统一接口。

模块覆盖的能力:
- 账号密码登录、注册、退出与令牌刷新
- 图形验证码与短信验证码
- 第三方社交登录(企业微信、钉钉、飞书)
- OAuth2 授权框架(客户端、令牌、授权页、用户信息)
- 登录日志与在线会话的打通(详见“日志与监控”“监控与连接”章节)
涉及的核心接口前缀:
text
/system/auth 账号密码登录、注册、刷新、退出、权限信息、社交登录、短信
/system/captcha 图形验证码
/system/oauth2 OAuth2 授权(令牌下发、校验、吊销、授权页)
/system/oauth2-client OAuth2 客户端管理
/system/oauth2-token OAuth2 令牌管理
/system/oauth2/user OAuth2 当前用户信息
/system/social-client 社交客户端(第三方应用凭据)管理
/system/social-user 社交用户与绑定关系管理认证模型与令牌体系
登录成功后,后端并不使用「用户 ID」作为令牌主体,而是生成一个随机的 session_id,把它同时作为 JWT 的 sub(主体)和 Redis 中会话信息的键。这样令牌本身不直接携带用户敏感信息,吊销/踢人只需删除 Redis 中的会话即可。
JWT 载荷(JWTPayloadSchema)仅包含三个字段:
sub:会话编号session_idis_refresh:是否为刷新令牌,用于区分两种令牌的用途exp:过期时间
令牌有效期由配置项控制(默认均为 12 小时):
ACCESS_TOKEN_EXPIRE_SECONDSREFRESH_TOKEN_EXPIRE_SECONDSTOKEN_TYPE:令牌类型,默认Bearer,前端在请求头中以Authorization: Bearer <token>携带
Redis 中各类认证相关键:
| 键 | 内容 | 过期 |
|---|---|---|
USER_SESSION:{session_id} | 在线会话 JSON(用户、IP、终端、登录时间等) | 刷新令牌有效期 |
ACCESS_TOKEN:{session_id} | 访问令牌 | 访问令牌有效期 |
REFRESH_TOKEN:{session_id} | 刷新令牌 | 刷新令牌有效期 |
CAPTCHA_CODES:{key} | 图形验证码答案 | CAPTCHA_EXPIRE_SECONDS |
sms_code:{mobile}:{scene} | 短信验证码 | 300 秒 |
oauth_state:{state} | provider|frontend_redirect | 600 秒 |
账号密码登录
账号密码登录是主登录链路,整体流程如下:
要点说明:
- 当
CAPTCHA_ENABLE=true且请求来源不是接口文档页时,必须携带图形验证码;captchaVerification的格式为key___code(___三段式分隔)。 - 登录参数中的
loginType支持PC端/移动端,用于在在线用户与日志中区分终端类型。 - 任何失败(验证码错误、账号密码错误、账号停用)都会写入登录日志,便于安全审计。
接口参考:
POST /system/auth/login:账号密码登录,返回令牌与过期时间POST /system/auth/login-form:兼容 Swagger UI 的 OAuth2 密码模式表单登录(不对外公开)
图形验证码
验证码用于拦截机器批量撞库。流程为前端先拉取一张验证码图片,提交登录时带回其标识与用户识别值。
POST /system/captcha/get:返回一个 Base64 图片imgBase、验证码标识key,以及当前是否启用的enablePOST /system/captcha/check:主动校验(可选,登录时后端自动校验)
验证码答案仅存于 Redis,校验成功后立即删除,且一次性使用。开关由 CAPTCHA_ENABLE 控制,有效期为 CAPTCHA_EXPIRE_SECONDS。
注册
POST /system/auth/register 提供用户自助注册能力,与登录复用同一套验证码与密码校验逻辑:
- 若开启验证码,注册前需校验
captchaVerification - 密码需满足长度与强度要求,且两次输入一致
- 注册成功后会自动签发令牌并写入注册日志,无需再次登录
令牌刷新与退出登录
刷新令牌
POST /system/auth/refresh-token?refreshToken=xxx 用于在无感知情况下续期访问令牌。后端会:
- 校验传入的是否为刷新令牌(
is_refresh=true) - 校验 Redis 中的会话是否仍然存在(已过期则需重新登录)
- 重新签发
access_token与refresh_token,并延长会话 TTL
刷新操作同样写入登录日志,便于追踪异常换票行为。
退出登录
POST /system/auth/logout 需在请求头携带 Authorization: Bearer <token>。后端解析出 session_id 后,删除 Redis 中对应的会话、访问令牌、刷新令牌三处键,并写入退出日志。删除会话的同时也就让该用户的在线记录失效。
登录后权限信息下发
登录成功后,前端需要获取当前用户的菜单与按钮权限,以渲染侧边栏与按钮级鉴权。这是通过一次聚合接口完成的:
GET /system/auth/get-permission-info
返回结构(聚合自 user / roles / menus / permissions):
实现要点:
menus是从用户所属角色递归构建的菜单树,已过滤停用状态与按钮类型(type=3)节点permissions单独从角色的全部菜单中收集按钮类型节点的权限标识(如system:user:query),用于前端useAccess/v-access按钮鉴权(详见“权限集成”章节)- 由于认证依赖加载的用户对象与会话绑定,接口内会使用请求级活跃会话重新加载角色与菜单,避免跨会话懒加载失败
短信验证码登录与重置密码
针对手机号用户,系统提供短信验证码登录与找回密码能力,场景由 scene 区分:
| scene | 场景 | 短信模板 |
|---|---|---|
| 21 | 登录 | admin-sms-login |
| 22 | 注册 | admin-sms-register |
| 23 | 重置密码 | admin-reset-password |
流程:
POST /system/auth/send-sms-code:传入mobile与scene,后端生成 6 位验证码写入 Redis(300 秒有效)并通过短信渠道下发POST /system/auth/sms-login:传入mobile与code,校验通过后按手机号查找用户并签发令牌(验证码一次性消费)POST /system/auth/reset-password:传入mobile、code、password,校验通过后更新该手机号用户的密码
短信渠道未配置(如本地调试)时,发送会失败但验证码仍保留在 Redis,便于本地联调。
第三方社交登录
社交登录支持企业微信、钉钉、飞书等渠道,由 SocialTypeEnum 统一枚举。第三方应用的 client_id / client_secret 等凭据维护在「社交客户端」表中(见下文)。
浏览器跳转模式(推荐)
适用于前端页面点击第三方图标后由浏览器发起授权的场景:
关键接口:
GET /system/auth/social-auth-redirect:返回 302 跳转,必须让浏览器直接导航(window.location.href),不能通过 axios 跟随跨域 302GET /system/auth/oauth/{provider}/callback:第三方授权后回跳,完成登录后重定向回前端(成功带access_token,失败带oauth_error)POST /system/auth/social-login:社交快捷登录,直接传入type/code/state完成登录(适用于前端已自行拿到授权码的场景)
安全设计:
state随机串存入 Redis 并校验,防止 CSRF / 重放- 前端回跳地址
redirectUri需命中OAUTH_REDIRECT_ALLOWED_HOSTS白名单,否则拒绝跳转,避免开放重定向 - 未绑定系统用户的社交账号,会在首次登录时自动注册系统用户并写入绑定关系
社交客户端与社交用户管理
- 「社交客户端」
/system/social-client:维护各渠道的client_id、client_secret、应用名、状态等,登录时按social_type读取凭据 - 「社交用户」
/system/social-user:记录第三方openid、昵称、头像、令牌等,并提供当前用户的绑定/解绑接口(/get-bind-list、/bind、/unbind)
相关表:system_social_client、system_social_user、system_social_user_bind。
OAuth2 授权框架
除社交登录外,系统内置一套完整的 OAuth2 授权服务器,使得第三方应用可以「代表用户」访问本系统开放接口。核心模型见 system_oauth2_client(客户端)、system_oauth2_access_token(令牌)、system_oauth2_code(授权码)、system_oauth2_approve(批准记录)、system_oauth2_refresh_token(刷新令牌)。
支持的授权类型(Oauth2GrantType):
authorization_code授权码模式implicit简化模式password密码模式client_credentials客户端模式refresh_token刷新令牌
开放接口(/system/oauth2):
POST /system/oauth2/token:获取访问令牌,需在Authorization头中通过 Basic 传递client_id:client_secretPOST /system/oauth2/check-token:校验令牌DELETE /system/oauth2/token:吊销令牌GET/POST /system/oauth2/authorize:授权页信息获取与授权申请(授权码/简化模式使用)GET/PUT /system/oauth2/user:当前 OAuth2 用户基本信息
管理接口:/system/oauth2-client(客户端 CRUD)、/system/oauth2-token(令牌分页与吊销)。
前端
apps/web-ele/src/views/system/oauth2提供客户端管理页与令牌管理页;views/_core/authentication/sso-login.vue是用户侧授权同意页。
前端相关
前端登录相关代码集中在 apps/web-ele/src/api/core/auth.ts 与认证 UI 组件 packages/effects/common-ui/src/ui/authentication:
loginApi/refreshTokenApi/logoutApi:分别对应登录、刷新、退出getAuthPermissionInfoApi:获取user / roles / menus / permissionsgetCaptcha/sendSmsCode/smsLogin/register/smsResetPassword:验证码与短信链路socialAuthRedirect/socialLogin:社交登录(前者返回完整 URL 由浏览器跳转)- 登录页组件包括账号登录、手机号验证码登录(
code-login)、二维码登录(qrcode-login)、钉钉登录(dingding-login)、注册(register)、忘记密码(forget-password)
典型前端登录时序:
约定:
- 请求统一在
Authorization头携带Bearer <accessToken> - 访问令牌临近过期时,前端拦截器使用
refreshToken静默刷新,失败则跳转登录页 - 权限信息中的
permissions配合useAccess与v-access实现按钮级鉴权
安全设计要点
- 会话与令牌分离:JWT 不直接携带用户主体,仅持有
session_id,吊销/踢人通过删除 Redis 会话实现 - 验证码一次性:图形与短信验证码校验成功后立即删除,防止重放
- 登录全链路审计:无论成功或失败(验证码错误、账号密码错误、账号停用、刷新、退出),均写入登录日志
- 社交登录防开放重定向:前端回跳地址必须命中
OAUTH_REDIRECT_ALLOWED_HOSTS白名单;state机制防 CSRF - OAuth2 客户端隔离:第三方应用通过
client_id/secret认证,授权范围scope由用户在授权页确认