
- 修改Package.swift以支持iOS 15和macOS 12。 - 更新swift-tca-architecture-guidelines.mdc中的alwaysApply设置为false。 - 注释掉AppDelegate中的NIMSDK导入,移除不再使用的NIMConfigurationManager和NIMSessionManager文件。 - 添加新的API相关文件,包括EMailLoginFeature、IDLoginFeature和相关视图,增强登录功能。 - 更新APIConstants和APIEndpoints以反映新的API路径。 - 添加本地化支持文件,包含英文和中文简体的本地化字符串。 - 新增字体管理和安全工具类,支持AES和DES加密。 - 更新Xcode项目配置,调整版本号和启动画面设置。
8.7 KiB
8.7 KiB
OAuth/Ticket 认证系统 API 文档
概述
本文档描述了 YuMi 应用中 OAuth 认证和 Ticket 会话管理的完整流程。系统采用两阶段认证机制:
- OAuth 阶段:用户登录获取
access_token
- Ticket 阶段:使用
access_token
获取业务会话ticket
认证流程架构
核心组件
- AccountInfoStorage: 负责账户信息和 ticket 的本地存储
- HttpRequestHelper: 网络请求管理,自动添加认证头
- Api+Login: 登录相关 API 接口
- Api+Main: Ticket 获取相关 API 接口
认证数据模型
AccountModel
@interface AccountModel : PIBaseModel
@property (nonatomic, assign) NSString *uid; // 用户唯一标识
@property (nonatomic, copy) NSString *jti; // JWT ID
@property (nonatomic, copy) NSString *token_type; // Token 类型
@property (nonatomic, copy) NSString *refresh_token; // 刷新令牌
@property (nonatomic, copy) NSString *netEaseToken; // 网易云信令牌
@property (nonatomic, copy) NSString *access_token; // OAuth 访问令牌
@property (nonatomic, assign) NSNumber *expires_in; // 过期时间
@end
API 接口详情
1. OAuth 登录接口
1.1 手机验证码登录
+ (void)loginWithCode:(HttpRequestHelperCompletion)completion
phone:(NSString *)phone
code:(NSString *)code
client_secret:(NSString *)client_secret
version:(NSString *)version
client_id:(NSString *)client_id
grant_type:(NSString *)grant_type
phoneAreaCode:(NSString *)phoneAreaCode;
接口路径: POST /oauth/token
请求参数:
参数名 | 类型 | 必填 | 描述 |
---|---|---|---|
phone | String | 是 | 手机号(DES加密) |
code | String | 是 | 验证码 |
client_secret | String | 是 | 客户端密钥,固定值:"uyzjdhds" |
version | String | 是 | 版本号,固定值:"1" |
client_id | String | 是 | 客户端ID,固定值:"erban-client" |
grant_type | String | 是 | 授权类型,验证码登录为:"sms_code" |
phoneAreaCode | String | 是 | 手机区号 |
返回数据: AccountModel 对象
1.2 手机密码登录
+ (void)loginWithPassword:(HttpRequestHelperCompletion)completion
phone:(NSString *)phone
password:(NSString *)password
client_secret:(NSString *)client_secret
version:(NSString *)version
client_id:(NSString *)client_id
grant_type:(NSString *)grant_type;
接口路径: POST /oauth/token
请求参数:
参数名 | 类型 | 必填 | 描述 |
---|---|---|---|
phone | String | 是 | 手机号(DES加密) |
password | String | 是 | 密码(DES加密) |
client_secret | String | 是 | 客户端密钥 |
version | String | 是 | 版本号 |
client_id | String | 是 | 客户端ID |
grant_type | String | 是 | 授权类型,密码登录为:"password" |
1.3 第三方登录
+ (void)loginWithThirdPart:(HttpRequestHelperCompletion)completion
openid:(NSString *)openid
unionid:(NSString *)unionid
access_token:(NSString *)access_token
type:(NSString *)type;
接口路径: POST /acc/third/login
请求参数:
参数名 | 类型 | 必填 | 描述 |
---|---|---|---|
openid | String | 是 | 第三方平台用户唯一标识 |
unionid | String | 是 | 第三方平台联合ID |
access_token | String | 是 | 第三方平台访问令牌 |
type | String | 是 | 第三方平台类型(1:Apple, 2:Facebook, 3:Google等) |
2. Ticket 获取接口
2.1 获取 Ticket
+ (void)requestTicket:(HttpRequestHelperCompletion)completion
access_token:(NSString *)accessToken
issue_type:(NSString *)issueType;
接口路径: POST /oauth/ticket
请求参数:
参数名 | 类型 | 必填 | 描述 |
---|---|---|---|
access_token | String | 是 | OAuth 登录获取的访问令牌 |
issue_type | String | 是 | 签发类型,固定值:"multi" |
返回数据:
{
"code": 200,
"data": {
"tickets": [
{
"ticket": "eyJhbGciOiJIUzI1NiJ9..."
}
]
}
}
3. HTTP 请求头配置
所有业务 API 请求都会自动添加以下请求头:
// 在 HttpRequestHelper 中自动配置
- (void)setupHeader {
AFHTTPSessionManager *client = [HttpRequestHelper requestManager];
// 用户ID头
if ([[AccountInfoStorage instance] getUid].length > 0) {
[client.requestSerializer setValue:[[AccountInfoStorage instance] getUid]
forHTTPHeaderField:@"pub_uid"];
}
// Ticket 认证头
if ([[AccountInfoStorage instance] getTicket].length > 0) {
[client.requestSerializer setValue:[[AccountInfoStorage instance] getTicket]
forHTTPHeaderField:@"pub_ticket"];
}
// 其他公共头
[client.requestSerializer setValue:[NSBundle uploadLanguageText]
forHTTPHeaderField:@"Accept-Language"];
[client.requestSerializer setValue:PI_App_Version
forHTTPHeaderField:@"App-Version"];
}
使用流程
完整登录流程示例
// 1. 用户登录获取 access_token
[Api loginWithCode:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
if (code == 200) {
// 保存账户信息
AccountModel *accountModel = [AccountModel modelWithDictionary:data.data];
[[AccountInfoStorage instance] saveAccountInfo:accountModel];
// 2. 使用 access_token 获取 ticket
[Api requestTicket:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
if (code == 200) {
NSArray *tickets = [data.data valueForKey:@"tickets"];
NSString *ticket = [tickets[0] valueForKey:@"ticket"];
// 保存 ticket
[[AccountInfoStorage instance] saveTicket:ticket];
// 3. 登录成功,可以进行业务操作
[self navigateToMainPage];
}
} access_token:accountModel.access_token issue_type:@"multi"];
}
} phone:encryptedPhone
code:verificationCode
client_secret:@"uyzjdhds"
version:@"1"
client_id:@"erban-client"
grant_type:@"sms_code"
phoneAreaCode:areaCode];
自动登录流程
- (void)autoLogin {
// 检查本地是否有账户信息
AccountModel *accountModel = [[AccountInfoStorage instance] getCurrentAccountInfo];
if (accountModel == nil || accountModel.access_token == nil) {
[self tokenInvalid]; // 跳转到登录页
return;
}
// 检查是否有有效的 ticket
if ([[AccountInfoStorage instance] getTicket].length > 0) {
[[self getView] autoLoginSuccess];
return;
}
// 使用 access_token 重新获取 ticket
[Api requestTicket:^(BaseModel * _Nonnull data) {
NSArray *tickets = [data.data valueForKey:@"tickets"];
NSString *ticket = [tickets[0] valueForKey:@"ticket"];
[[AccountInfoStorage instance] saveTicket:ticket];
[[self getView] autoLoginSuccess];
} fail:^(NSInteger code, NSString * _Nullable msg) {
[self logout]; // ticket 获取失败,重新登录
} access_token:accountModel.access_token issue_type:@"multi"];
}
错误处理
401 未授权错误
当接收到 401 状态码时,系统会自动处理:
// 在 HttpRequestHelper 中
if (response && response.statusCode == 401) {
failure(response.statusCode, YMLocalizedString(@"HttpRequestHelper7"));
// 通常需要重新登录
}
Ticket 过期处理
- Ticket 过期时服务器返回 401 错误
- 客户端应该使用保存的
access_token
重新获取 ticket - 如果
access_token
也过期,则需要用户重新登录
安全注意事项
- 数据加密: 敏感信息(手机号、密码)使用 DES 加密传输
- 本地存储:
access_token
存储在文件系统中ticket
存储在内存中,应用重启需重新获取
- 请求头: 所有业务请求自动携带
pub_uid
和pub_ticket
头 - 错误处理: 建立完善的 401 错误重试机制
相关文件
YuMi/Structure/MVP/Model/AccountInfoStorage.h/m
- 账户信息存储管理YuMi/Modules/YMLogin/Api/Api+Login.h/m
- 登录相关接口YuMi/Modules/YMTabbar/Api/Api+Main.h/m
- Ticket 获取接口YuMi/Network/HttpRequestHelper.h/m
- 网络请求管理YuMi/Structure/MVP/Model/AccountModel.h/m
- 账户数据模型