2025-12-02 18:29:04 +08:00
|
|
|
|
//
|
|
|
|
|
|
// KBUserSessionManager.m
|
|
|
|
|
|
// keyBoard
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by Mac on 2025/12/1.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#import "KBUserSessionManager.h"
|
|
|
|
|
|
#import "KBAuthManager.h"
|
|
|
|
|
|
#import "KBUser.h"
|
|
|
|
|
|
#import "KBConfig.h"
|
|
|
|
|
|
#import <MJExtension/MJExtension.h>
|
2025-12-03 14:30:02 +08:00
|
|
|
|
#import "KBLoginVC.h"
|
2025-12-02 18:29:04 +08:00
|
|
|
|
/// App Group 里的用户缓存 key
|
|
|
|
|
|
static NSString * const kKBSessionUserStoreKey = @"KBSession.currentUser";
|
|
|
|
|
|
/// “本次安装是否已初始化”标记 key(用来识别卸载重装)
|
|
|
|
|
|
static NSString * const kKBSessionInstallFlagKey = @"KBSession.installInitialized";
|
|
|
|
|
|
|
|
|
|
|
|
@interface KBUserSessionManager ()
|
|
|
|
|
|
@property (nonatomic, strong) NSUserDefaults *defaults;
|
|
|
|
|
|
@property (atomic, strong, readwrite, nullable) KBUser *currentUser;
|
|
|
|
|
|
@property (nonatomic, assign) BOOL didBootstrap;
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation KBUserSessionManager
|
|
|
|
|
|
|
|
|
|
|
|
+ (instancetype)shared {
|
|
|
|
|
|
static KBUserSessionManager *m;
|
|
|
|
|
|
static dispatch_once_t onceToken;
|
|
|
|
|
|
dispatch_once(&onceToken, ^{
|
|
|
|
|
|
m = [KBUserSessionManager new];
|
|
|
|
|
|
});
|
|
|
|
|
|
return m;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (instancetype)init {
|
|
|
|
|
|
if (self = [super init]) {
|
|
|
|
|
|
// 优先用 App Group 的 UserDefaults,App 和扩展共用一份
|
|
|
|
|
|
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
|
|
|
|
|
_defaults = ud ?: [NSUserDefaults standardUserDefaults];
|
|
|
|
|
|
|
|
|
|
|
|
// 监听 token 变化(例如别处调用了 signOut)
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
|
|
selector:@selector(_onAuthChanged:)
|
|
|
|
|
|
name:KBAuthChangedNotification
|
|
|
|
|
|
object:nil];
|
|
|
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Public
|
|
|
|
|
|
|
|
|
|
|
|
- (void)bootstrapIfNeeded {
|
|
|
|
|
|
if (self.didBootstrap) return;
|
|
|
|
|
|
self.didBootstrap = YES;
|
|
|
|
|
|
|
2025-12-03 14:30:02 +08:00
|
|
|
|
// 使用本 App 的 standardUserDefaults 记录“本次安装是否已初始化”。
|
|
|
|
|
|
// 这样在卸载重装后,这个标记会被系统清空,从而触发一次性清理旧的 Keychain token。
|
|
|
|
|
|
NSUserDefaults *installDefaults = [NSUserDefaults standardUserDefaults];
|
|
|
|
|
|
BOOL hasInitializedThisInstall = [installDefaults boolForKey:kKBSessionInstallFlagKey];
|
2025-12-02 18:29:04 +08:00
|
|
|
|
|
|
|
|
|
|
KBAuthManager *auth = [KBAuthManager shared]; // 内部会 reloadFromKeychain
|
|
|
|
|
|
|
|
|
|
|
|
if (!hasInitializedThisInstall) {
|
|
|
|
|
|
// 说明是“卸载重装后的第一次运行”(或者真正第一次安装)
|
2025-12-03 14:30:02 +08:00
|
|
|
|
[installDefaults setBool:YES forKey:kKBSessionInstallFlagKey];
|
|
|
|
|
|
[installDefaults synchronize];
|
2025-12-02 18:29:04 +08:00
|
|
|
|
|
|
|
|
|
|
// 若此时 Keychain 里已有 token,多半是上一次安装遗留的;按你的需求清掉
|
|
|
|
|
|
if (auth.current.accessToken.length > 0) {
|
|
|
|
|
|
[auth signOut];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清除旧的用户缓存
|
|
|
|
|
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
|
|
|
|
|
[self.defaults synchronize];
|
|
|
|
|
|
self.currentUser = nil;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 正常启动:从本地恢复用户信息
|
|
|
|
|
|
[self p_loadUserFromStore];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (BOOL)isLoggedIn {
|
|
|
|
|
|
return [[KBAuthManager shared] isLoggedIn];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (NSString *)accessToken {
|
|
|
|
|
|
return [KBAuthManager shared].current.accessToken;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)handleLoginSuccessWithUser:(KBUser *)user {
|
|
|
|
|
|
if (!user) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 先写 Keychain(统一走 KBAuthManager)
|
|
|
|
|
|
NSString *token = user.token;
|
|
|
|
|
|
if (token.length > 0) {
|
|
|
|
|
|
[[KBAuthManager shared] saveAccessToken:token
|
2025-12-02 20:33:17 +08:00
|
|
|
|
refreshToken:nil
|
|
|
|
|
|
expiryDate:nil
|
|
|
|
|
|
userIdentifier:nil];
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 再缓存用户信息,供 App/键盘使用
|
|
|
|
|
|
self.currentUser = user;
|
|
|
|
|
|
[self p_saveUserToStore:user];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)logout {
|
|
|
|
|
|
// 清 Keychain
|
|
|
|
|
|
[[KBAuthManager shared] signOut];
|
|
|
|
|
|
|
|
|
|
|
|
// 清本地用户缓存
|
|
|
|
|
|
self.currentUser = nil;
|
|
|
|
|
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
|
|
|
|
|
[self.defaults synchronize];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Private
|
|
|
|
|
|
|
|
|
|
|
|
- (void)p_loadUserFromStore {
|
|
|
|
|
|
id obj = [self.defaults objectForKey:kKBSessionUserStoreKey];
|
|
|
|
|
|
if (![obj isKindOfClass:[NSDictionary class]]) {
|
|
|
|
|
|
self.currentUser = nil;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
KBUser *user = [KBUser mj_objectWithKeyValues:(NSDictionary *)obj];
|
|
|
|
|
|
self.currentUser = user;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)p_saveUserToStore:(KBUser *)user {
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
|
|
|
|
|
[self.defaults synchronize];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
NSDictionary *dict = [user mj_keyValues];
|
|
|
|
|
|
if (dict) {
|
|
|
|
|
|
[self.defaults setObject:dict forKey:kKBSessionUserStoreKey];
|
|
|
|
|
|
[self.defaults synchronize];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)_onAuthChanged:(NSNotification *)note {
|
2025-12-03 12:55:51 +08:00
|
|
|
|
// 避免在 KBAuthManager 的 +shared 初始化过程中再次调用 +shared 造成递归,
|
|
|
|
|
|
// 这里直接使用通知携带的实例。
|
|
|
|
|
|
KBAuthManager *auth = nil;
|
|
|
|
|
|
if ([note.object isKindOfClass:[KBAuthManager class]]) {
|
|
|
|
|
|
auth = (KBAuthManager *)note.object;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
auth = [KBAuthManager shared];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-02 18:29:04 +08:00
|
|
|
|
// 如果 token 被别处清掉了,这里同步清一下 currentUser
|
2025-12-03 12:55:51 +08:00
|
|
|
|
if (![auth isLoggedIn]) {
|
2025-12-02 18:29:04 +08:00
|
|
|
|
self.currentUser = nil;
|
|
|
|
|
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
|
|
|
|
|
[self.defaults synchronize];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 14:30:02 +08:00
|
|
|
|
- (void)goLoginVC{
|
|
|
|
|
|
KBLoginVC *vc = [[KBLoginVC alloc] init];
|
|
|
|
|
|
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-02 18:29:04 +08:00
|
|
|
|
@end
|