4271f333b6
- 2026-06-07-sys-app-management: 已批准,待实现 → 已实现 - 2026-06-07-multi-login-social-login: 已批准,待实现 → 已实现 - 2026-06-06-user-aggregate-query: 已批准 → 已实现 各 spec 对应的 plan 已结清/实施 commit 已落地,更新状态描述并补充实施情况指引。
28 KiB
28 KiB
多方式登录与第三方登录设计文档
日期: 2026-06-07
状态: 已实现(2026-06-07)
作者: AI Assistant 实施情况: 数据库变更、实体调整、UserSocial 增删、密码登录扩展、短信/微信/支付宝框架、OAuth2ServerConfig 注册、配置更新、编译验证共 12 任务全部完成,详见docs/superpowers/plans/2026-06-07-multi-login-social-login-plan.md与 git log6fd82fb起各 commit。
1. 背景与目标
1.1 现状
当前系统仅支持用户名密码登录(grant_type=password),且 PasswordAuthenticationConverter 只提取 username 参数,无法支持手机号、邮箱登录。微信、支付宝、短信登录的 Converter 和 Provider 均为空实现。
1.2 目标
- 扩展密码登录:支持用户名、手机号、邮箱三种账号类型登录
- 实现短信登录:框架结构先行,验证码逻辑后续填充
- 实现微信登录:支持微信授权码换取用户信息并自动创建账号
- 实现支付宝登录:支持支付宝授权码换取用户信息并自动创建账号
- 第三方账号管理:存储 openId/unionId,支持 unionId 优先查询
- 手机号为主键:系统以手机号作为用户唯一标识,第三方登录自动创建新用户
- 字段迁移:将
email从uc_user_detail迁移到uc_user表
2. 核心设计原则
- 独立授权模式:每种登录方式使用独立的
grant_type,符合 OAuth2 扩展规范 - 手机号唯一性:手机号是系统用户的唯一标识,第三方登录时优先用手机号创建/查找用户
- 自动创建用户:第三方登录无手机号时,自动生成
userNo作为用户名,后续用户可自行修改 - unionId 优先:查询第三方用户信息时,优先使用 unionId,其次使用 openId
- 向后兼容:保留现有
password模式的username参数,同时新增account+accountType参数
3. 架构设计
3.1 整体架构
前端调用
│
▼
POST /oauth2/token
│
▼
┌─────────────────────────────────────┐
│ DelegatingAuthenticationConverter │
│ ┌─────────┐ ┌─────┐ ┌─────────┐ │
│ │ Password│ │ Sms │ │ Wechat │ │
│ │ Converter│ │Converter│ │Converter│ │
│ └─────────┘ └─────┘ └─────────┘ │
│ ┌─────────┐ │
│ │ Alipay │ │
│ │Converter│ │
│ └─────────┘ │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ AuthenticationProvider 链 │
│ ┌─────────┐ ┌─────┐ ┌─────────┐ │
│ │ Password│ │ Sms │ │ Wechat │ │
│ │ Provider│ │Provider│ │Provider│ │
│ └─────────┘ └─────┘ └─────────┘ │
│ ┌─────────┐ │
│ │ Alipay │ │
│ │Provider │ │
│ └─────────┘ │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 用户查找 / 创建 / 绑定 │
│ • 根据手机号/用户名/邮箱查找用户 │
│ • 第三方登录:调平台API获取用户信息 │
│ • 自动创建新用户(手机号或userNo) │
│ • 记录第三方绑定关系 │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 生成 OAuth2 Token │
│ Access Token + Refresh Token │
└─────────────────────────────────────┘
3.2 登录方式对照表
| 登录方式 | grant_type | 必填参数 | 可选参数 | 说明 |
|---|---|---|---|---|
| 用户名密码 | password |
username, password |
- | 兼容现有方式 |
| 手机号密码 | password |
account, accountType=PHONE, password |
- | 扩展方式 |
| 邮箱密码 | password |
account, accountType=EMAIL, password |
- | 扩展方式 |
| 短信验证码 | sms |
phone, code |
- | 框架先行 |
| 微信登录 | wechat |
code |
phone |
授权码模式 |
| 支付宝登录 | alipay |
code |
phone |
授权码模式 |
4. 数据库设计
4.1 新增表:rui_uc_user_social
存储用户与第三方平台的绑定关系。
CREATE TABLE rui_uc_user_social (
id BIGINT NOT NULL,
tenant_id BIGINT NOT NULL DEFAULT 0 COMMENT '租户ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
provider VARCHAR(20) NOT NULL COMMENT '平台 wechat/alipay',
union_id VARCHAR(100) DEFAULT NULL COMMENT 'unionId(微信开放平台)',
open_id VARCHAR(100) NOT NULL COMMENT 'openId',
extra JSON DEFAULT NULL COMMENT '扩展信息(昵称、头像等)',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_user_provider (user_id, provider),
UNIQUE KEY uk_provider_openid (provider, open_id),
INDEX idx_union_id (union_id),
INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户第三方账号关联';
字段说明:
provider: 平台标识,wechat或alipayunion_id: 微信开放平台统一标识,同一主体下的不同应用 unionId 相同open_id: 各应用内的唯一标识extra: JSON 格式,存储第三方平台的额外信息(昵称、头像、性别等)
索引设计:
uk_user_provider: 一个用户在同一平台只能绑定一个账号uk_provider_openid: 同一平台的 openId 唯一idx_union_id: 支持 unionId 查询
4.2 修改表:rui_uc_user
新增 email 字段:
-- 在 rui_uc_user 表中添加 email 字段
ALTER TABLE rui_uc_user ADD COLUMN email VARCHAR(100) DEFAULT NULL COMMENT '邮箱' AFTER phone;
ALTER TABLE rui_uc_user ADD UNIQUE KEY uk_email (tenant_id, email);
修改后的表结构:
CREATE TABLE rui_uc_user (
id BIGINT NOT NULL,
tenant_id BIGINT NOT NULL DEFAULT 0 COMMENT '租户ID 0:系统级',
username VARCHAR(100) NOT NULL COMMENT '用户名',
phone VARCHAR(20) DEFAULT NULL COMMENT '手机号',
email VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
user_no VARCHAR(50) DEFAULT NULL COMMENT '用户编号(短编码,前端展示用)',
password VARCHAR(255) NOT NULL COMMENT '密码(BCrypt加密)',
user_type TINYINT NOT NULL DEFAULT 1 COMMENT '用户类型 1:普通用户 2:管理员 3:系统用户',
status TINYINT NOT NULL DEFAULT 1 COMMENT '状态 0:禁用 1:启用',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除 0:正常 1:已删',
created_by BIGINT DEFAULT NULL COMMENT '创建者ID',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_by BIGINT DEFAULT NULL COMMENT '更新者ID',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_username (tenant_id, username),
UNIQUE KEY uk_phone (tenant_id, phone),
UNIQUE KEY uk_email (tenant_id, email),
INDEX idx_tenant (tenant_id),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户';
4.3 修改表:rui_uc_user_detail
删除 email 字段:
-- 从 rui_uc_user_detail 表中删除 email 字段
ALTER TABLE rui_uc_user_detail DROP COLUMN email;
4.4 登录日志扩展
rui_sys_login_log 表的 login_type 字段已有定义:
1: 密码登录2: 短信登录3: 微信登录4: 支付宝登录
无需修改,但需要在代码中确保所有登录方式都正确记录类型。
5. 核心流程设计
5.1 密码登录流程(扩展)
前端请求
│
▼
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {client_credentials}
# 方式1:用户名密码(兼容现有)
grant_type=password
&username=admin
&password=123456
# 方式2:手机号密码(新增)
grant_type=password
&account=13800138000
&accountType=PHONE
&password=123456
# 方式3:邮箱密码(新增)
grant_type=password
&account=user@example.com
&accountType=EMAIL
&password=123456
│
▼
PasswordAuthenticationConverter
├─ 提取 grant_type=password
├─ 如果有 username → 走兼容模式
└─ 如果有 account + accountType → 走扩展模式
│
▼
PasswordAuthenticationProvider
├─ 校验客户端支持 password 授权
├─ 构建 UsernamePasswordAuthenticationToken
│ ├─ 兼容模式: username 作为 principal
│ └─ 扩展模式: account 作为 principal
│
▼
AuthenticationManager
│
▼
DaoAuthenticationProvider
├─ 调用 RemoteUserDetailsService.loadUserByUsername(username)
│ 或 RemoteUserDetailsService.loadUserByAccount(account, accountType)
│
▼
RemoteUserDetailsService
├─ USERNAME → userAuthFeign.loadUser(account)
├─ PHONE → userAuthFeign.loadUser({account, PHONE})
└─ EMAIL → userAuthFeign.loadUser({account, EMAIL})
│
▼
UserInnerController.loadUser(LoginAccountDTO)
├─ 根据 accountType 查询用户
├─ PHONE → lambdaQuery().eq(User::getPhone, account)
├─ EMAIL → lambdaQuery().eq(User::getEmail, account)
└─ USERNAME → lambdaQuery().eq(User::getUsername, account)
│
▼
返回 UserDetails → 生成 Token
5.2 短信登录流程
前端请求
│
▼
POST /oauth2/token
grant_type=sms
&phone=13800138000
&code=123456
│
▼
SmsAuthenticationConverter
├─ 校验 grant_type=sms
├─ 校验 phone 必填
└─ 校验 code 必填
│
▼
SmsAuthenticationProvider
├─ 校验客户端支持 sms 授权
├─ 从 Redis 获取验证码(key: sms:code:{phone})
├─ 比对验证码
├─ 验证码错误 → 抛出异常
└─ 验证码正确 → 继续
│
▼
根据 phone 查询用户
├─ 找到 → 生成 Token
└─ 未找到 → 创建新用户
├─ username = phone
├─ phone = phone
├─ password = 随机生成(BCrypt加密)
└─ user_no = 自动生成
│
▼
生成 OAuth2 Token
注意:短信验证码发送接口(POST /sms/send)本次不实现,只预留框架结构。Redis 中的验证码需要前端开发时手动设置或通过其他方式注入。
5.3 微信登录流程
前端请求
│
▼
POST /oauth2/token
grant_type=wechat
&code=wx_auth_code
&phone=13800138000 ← 可选
│
▼
WechatAuthenticationConverter
├─ 校验 grant_type=wechat
├─ 校验 code 必填
└─ 提取 phone(可选)
│
▼
WechatAuthenticationProvider
├─ 校验客户端支持 wechat 授权
├─ 调用微信 API 换取 access_token
│ GET https://api.weixin.qq.com/sns/oauth2/access_token
│ ?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code
│
├─ 获取 openId, unionId, access_token
│
├─ 根据 unionId 查询 rui_uc_user_social
│ ├─ 找到 → 获取 user_id → 查询用户 → 生成 Token
│ └─ 未找到 → 根据 openId 查询
│ ├─ 找到 → 获取 user_id → 查询用户 → 生成 Token
│ └─ 未找到 → 创建新用户
│
▼
创建新用户流程
├─ 有 phone 参数
│ ├─ 查询 phone 是否已存在
│ ├─ 存在 → 使用该用户,记录绑定关系
│ └─ 不存在 → 创建新用户
│ ├─ username = phone
│ ├─ phone = phone
│ └─ password = 随机生成
│
└─ 无 phone 参数
├─ username = 随机生成(如 WX_ + 时间戳)
├─ phone = null
└─ password = 随机生成
│
▼
记录绑定关系
INSERT INTO rui_uc_user_social
(user_id, provider, union_id, open_id, extra)
VALUES (?, 'wechat', ?, ?, ?)
│
▼
生成 OAuth2 Token
5.4 支付宝登录流程
与微信登录类似,区别:
- 调用支付宝 API:
alipay.system.oauth.token换取 access_token - 调用
alipay.user.info.share获取用户信息 - 支付宝没有 unionId,使用 userId 作为唯一标识
- 存储到
rui_uc_user_social时,union_id为 null
6. 代码结构
6.1 新增/修改文件清单
rui-common-oauth2 模块
rui-common-oauth2/src/main/java/com/rui/common/oauth2/
├── authentication/
│ ├── BaseAuthenticationConverter.java # 已有,无需修改
│ ├── BaseAuthenticationProvider.java # 已有,无需修改
│ ├── password/
│ │ ├── PasswordAuthenticationConverter.java # 修改:支持 accountType
│ │ └── PasswordAuthenticationProvider.java # 已有,无需修改
│ ├── sms/
│ │ ├── SmsAuthenticationConverter.java # 重写:实现短信参数提取
│ │ ├── SmsAuthenticationProvider.java # 重写:实现短信认证逻辑
│ │ └── SmsAuthenticationToken.java # 新增:短信认证令牌
│ ├── weixin/
│ │ ├── WeixinAuthenticationConverter.java # 重写:实现微信参数提取
│ │ ├── WeixinAuthenticationProvider.java # 重写:实现微信认证逻辑
│ │ └── WeixinAuthenticationToken.java # 新增:微信认证令牌
│ └── alipay/
│ ├── AlipayAuthenticationConverter.java # 重写:实现支付宝参数提取
│ ├── AlipayAuthenticationProvider.java # 重写:实现支付宝认证逻辑
│ └── AlipayAuthenticationToken.java # 新增:支付宝认证令牌
├── config/
│ └── OAuth2ServerConfig.java # 修改:注册新的 Converter 和 Provider
└── service/
└── RemoteUserDetailsService.java # 修改:支持 EMAIL 类型
rui-service-user 模块
rui-service-user/src/main/java/com/rui/service/user/
├── entity/
│ ├── User.java # 修改:新增 email 字段
│ ├── UserDetail.java # 修改:删除 email 字段
│ └── UserSocial.java # 新增:第三方账号关联实体
├── mapper/
│ └── UserSocialMapper.java # 新增
├── service/
│ ├── IUserSocialService.java # 新增
│ └── impl/
│ └── UserSocialServiceImpl.java # 新增
├── controller/
│ └── inner/
│ └── UserInnerController.java # 修改:支持 EMAIL 查询
└── dto/
└── LoginAccountDTO.java # 已有,无需修改
6.2 关键类设计
6.2.1 PasswordAuthenticationConverter(修改)
public class PasswordAuthenticationConverter extends BaseAuthenticationConverter<PasswordAuthenticationToken> {
@Override
public void checkParams(HttpServletRequest request) {
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
// 兼容模式:使用 username
String username = parameters.getFirst("username");
if (StringUtils.hasText(username)) {
// 校验 password
String password = parameters.getFirst("password");
if (!StringUtils.hasText(password)) {
OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, "password", ...);
}
return;
}
// 扩展模式:使用 account + accountType
String account = parameters.getFirst("account");
if (!StringUtils.hasText(account)) {
OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, "account", ...);
}
String accountType = parameters.getFirst("accountType");
if (!StringUtils.hasText(accountType)) {
OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, "accountType", ...);
}
// 校验 password
String password = parameters.getFirst("password");
if (!StringUtils.hasText(password)) {
OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, "password", ...);
}
}
@Override
public PasswordAuthenticationToken buildToken(...) {
// 将 accountType 放入 additionalParameters
// 供 Provider 使用
return new PasswordAuthenticationToken(...);
}
}
6.2.2 WechatAuthenticationProvider(重写)
@Slf4j
public class WechatAuthenticationProvider extends BaseAuthenticationProvider<WechatAuthenticationToken> {
private final WechatApiClient wechatApiClient;
private final UserSocialService userSocialService;
private final UserService userService;
@Override
public UsernamePasswordAuthenticationToken buildToken(Map<String, Object> reqParameters) {
String code = (String) reqParameters.get("code");
String phone = (String) reqParameters.get("phone");
// 调用微信 API 获取 openId, unionId
WechatTokenResponse wxResponse = wechatApiClient.getAccessToken(code);
String openId = wxResponse.getOpenid();
String unionId = wxResponse.getUnionid();
// 查找或创建用户
User user = findOrCreateUser(openId, unionId, phone);
// 构建认证令牌
return new UsernamePasswordAuthenticationToken(user.getUsername(), null);
}
private User findOrCreateUser(String openId, String unionId, String phone) {
// 1. 根据 unionId 查找
if (StringUtils.hasText(unionId)) {
UserSocial social = userSocialService.findByUnionId(unionId);
if (social != null) {
return userService.getById(social.getUserId());
}
}
// 2. 根据 openId 查找
UserSocial social = userSocialService.findByOpenId("wechat", openId);
if (social != null) {
return userService.getById(social.getUserId());
}
// 3. 创建新用户
User user = new User();
if (StringUtils.hasText(phone)) {
// 检查手机号是否已存在
User existUser = userService.findByPhone(phone);
if (existUser != null) {
user = existUser;
} else {
user.setUsername(phone);
user.setPhone(phone);
user.setPassword(generateRandomPassword());
userService.save(user);
}
} else {
// 无手机号,生成随机用户名
user.setUsername(generateRandomUsername());
user.setPassword(generateRandomPassword());
userService.save(user);
}
// 4. 记录绑定关系
UserSocial newSocial = new UserSocial();
newSocial.setUserId(user.getId());
newSocial.setProvider("wechat");
newSocial.setUnionId(unionId);
newSocial.setOpenId(openId);
userSocialService.save(newSocial);
return user;
}
}
6.2.3 UserSocial 实体
@Data
@TableName(value = "uc_user_social", keepGlobalPrefix = true)
public class UserSocial extends BaseEntity {
@Schema(description = "用户ID")
private Long userId;
@Schema(description = "平台 wechat/alipay")
private String provider;
@Schema(description = "unionId")
private String unionId;
@Schema(description = "openId")
private String openId;
@Schema(description = "扩展信息")
private String extra;
}
7. API 接口设计
7.1 密码登录
### 用户名密码登录(兼容现有)
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Q6
grant_type=password
&username=admin
&password=123456
&scope=server
### 手机号密码登录(新增)
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Q6
grant_type=password
&account=13800138000
&accountType=PHONE
&password=123456
&scope=server
### 邮箱密码登录(新增)
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Q6
grant_type=password
&account=user@example.com
&accountType=EMAIL
&password=123456
&scope=server
7.2 短信登录
### 短信验证码登录
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Q6
grant_type=sms
&phone=13800138000
&code=123456
&scope=server
7.3 微信登录
### 微信登录
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Q6
grant_type=wechat
&code=wx_auth_code_xxx
&phone=13800138000
&scope=server
7.4 支付宝登录
### 支付宝登录
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Qtc3ByaW5nLWJvb3Q6
grant_type=alipay
&code=alipay_auth_code_xxx
&phone=13800138000
&scope=server
7.5 响应格式
所有登录方式返回统一的 OAuth2 Token 响应:
{
"access_token": "abc123...",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "def456...",
"scope": "server"
}
8. 配置设计
8.1 微信配置
# Nacos 配置:rui-service-auth.yaml 或 rui-common.yaml
social:
wechat:
app-id: wx1234567890abcdef
app-secret: your-app-secret
# 可选:token 刷新地址
token-url: https://api.weixin.qq.com/sns/oauth2/access_token
# 可选:用户信息地址
user-info-url: https://api.weixin.qq.com/sns/userinfo
8.2 支付宝配置
social:
alipay:
app-id: 2024XXXXXXXXXXXX
private-key: your-private-key
public-key: alipay-public-key
# 可选:网关地址
gateway-url: https://openapi.alipay.com/gateway.do
8.3 客户端授权类型配置
修改 sys_oauth_client 表,为客户端添加新的授权类型:
-- 更新默认客户端,支持所有登录方式
UPDATE sys_oauth_client
SET grant_types = 'password,refresh_token,client_credentials,sms,wechat,alipay'
WHERE client_id = 'rui-client';
9. 安全设计
9.1 验证码安全
- 短信验证码有效期:5 分钟
- 验证码错误次数限制:5 次/小时
- 验证码存储:Redis,key =
sms:code:{phone}
9.2 第三方登录安全
- 微信/支付宝授权码只能使用一次
- 授权码有效期:5 分钟(由微信/支付宝平台控制)
- 后端必须校验授权码的真实性(调平台 API)
9.3 密码安全
- 第三方登录自动创建的用户,生成随机密码(32 位随机字符串)
- 用户首次设置密码时,要求提供原密码或通过手机验证码验证
10. 错误码设计
| 错误码 | 描述 | 场景 |
|---|---|---|
invalid_request |
请求参数错误 | 缺少必填参数、参数格式错误 |
invalid_grant |
授权失败 | 验证码错误、授权码无效 |
invalid_client |
客户端认证失败 | 客户端不存在、授权类型不支持 |
unauthorized_client |
客户端未授权 | 客户端不支持该授权类型 |
server_error |
服务器内部错误 | 调用第三方 API 失败 |
11. 测试策略
11.1 单元测试
PasswordAuthenticationConverterTest: 测试参数提取和校验SmsAuthenticationProviderTest: 测试验证码校验逻辑WechatAuthenticationProviderTest: Mock 微信 API,测试用户创建流程
11.2 集成测试
- 使用 H2 内存数据库测试完整登录流程
- 使用 WireMock 模拟微信/支付宝 API
11.3 手动测试清单
- 用户名密码登录(兼容测试)
- 手机号密码登录
- 邮箱密码登录
- 短信验证码登录(使用 Redis 手动设置验证码)
- 微信登录(使用测试授权码)
- 支付宝登录(使用测试授权码)
- 第三方登录后绑定手机号
- 同一微信不同手机号创建不同用户
- unionId 优先查询验证
12. 风险与回滚
12.1 风险
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| 微信/支付宝 API 变更 | 登录失败 | 封装 API 调用,便于快速适配 |
| 手机号重复 | 数据不一致 | 数据库唯一索引 + 代码校验 |
| 性能问题 | 登录慢 | Redis 缓存 + 异步记录日志 |
12.2 回滚方案
- 数据库变更:保留原字段,新增字段不影响现有数据
- 代码回滚:新授权模式独立实现,不影响现有
password模式 - 配置回滚:移除新 grant_type 即可禁用
13. 后续优化
- 短信服务商接入:实现真实的短信发送功能
- 社交账号解绑:提供 API 解除第三方绑定
- 多账号合并:支持将多个第三方账号合并到同一用户
- 登录设备管理:记录登录设备,支持远程登出
- 扫码登录:支持微信扫码登录 PC 端
14. 附录
14.1 登录类型枚举
public enum LoginType {
PASSWORD(1, "密码登录"),
SMS(2, "短信登录"),
WECHAT(3, "微信登录"),
ALIPAY(4, "支付宝登录");
private final int code;
private final String description;
LoginType(int code, String description) {
this.code = code;
this.description = description;
}
}
14.2 账号类型枚举
public enum AccountType {
USERNAME("用户名"),
PHONE("手机号"),
EMAIL("邮箱");
private final String description;
AccountType(String description) {
this.description = description;
}
}
14.3 第三方平台枚举
public enum SocialProvider {
WECHAT("微信"),
ALIPAY("支付宝");
private final String description;
SocialProvider(String description) {
this.description = description;
}
}
文档结束