// // RQUserManager.m // BuckDriverStudent // // Created by 张嵘 on 2019/10/24. // Copyright © 2019 RONG. All rights reserved. // #import "RQUserManager.h" //#import "RQHTTPService+RQUpdateUser.h" #import "RQLoginViewModel.h" #include /// 用户信息的名称 static NSString * const RQUserDataFileName = @"senba_empty_user.data"; /// 用户数据配置完成 NSString *const RQUserDataConfigureCompleteNotification = @"RQUserDataConfigureCompleteNotification"; /// 用户数据配置完成,取出userInfo 数据的的key NSString *const RQUserDataConfigureCompleteUserInfoKey = @"RQUserDataConfigureCompleteUserInfoKey"; @interface RQUserManager () /// currentLoginUser @property (nonatomic, readwrite, strong) RQUserModel *currentUser; @property (nonatomic, readwrite, assign) BOOL isObserve; @property (nonatomic, readwrite, strong) RQLoginViewModel *loginViewModel; @end @implementation RQUserManager static id rq_userManager = nil; #pragma mark - init + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ rq_userManager = [[self alloc] init]; }); return rq_userManager; } - (instancetype)init { if (self = [super init]) { } return self; } #pragma mark - Private Method - (void)saveUser:(RQUserModel *)user { /// 记录用户数据 self.currentUser = user; /// 保存 BOOL status = [NSKeyedArchiver archiveRootObject:user toFile:RQFilePathFromWeChatDoc(RQUserDataFileName)]; NSLog(@"Save login user data, the status is %@",status?@"Success...":@"Failure..."); if (_currentUser && !_isObserve) { [self beginObserveUser]; } } - (void)deleteUser:(RQUserModel *)user{ /// 删除 self.currentUser = nil; BOOL status = [RQFileManager removeFile:RQFilePathFromWeChatDoc(RQUserDataFileName)]; NSLog(@"Delete login user data , the status is %@",status?@"Success...":@"Failure..."); self.currentUser = nil; _isObserve = !status; self.isVip = 0; } - (RQUserModel *)currentUser { if (!_currentUser) { _currentUser = [NSKeyedUnarchiver unarchiveObjectWithFile:RQFilePathFromWeChatDoc(RQUserDataFileName) exception:nil]; if (_currentUser && !_isObserve) { [self beginObserveUser]; } } return _currentUser; } /// 是否登录 - (BOOL)isLogin { if (RQObjectIsNil(self.currentUser)) { return NO; } else { return YES; } } /// 是否需要登录 - (BOOL)isShouldLogin { if (RQObjectIsNil(self.currentUser)) { if (![RQControllerHelper.currentViewController isKindOfClass:[RQLoginViewController class]]) { [RQ_APPDELEGATE.services pushViewModel:self.loginViewModel animated:YES]; } return NO; } else { return YES; } } /// 获取当前用户的id - (NSString *)currentUserId { if ([self currentUser].thirdResult) { return RQStringIsNotEmpty(self.currentUser.userId)? self.currentUser.userId : @""; } else if ([self currentUser].appleUserInfo) { return [self currentUser].appleUserInfo.sub; } else { return @""; } } - (void)loginUser:(RQUserModel *)user{ /// 保存用户 [self saveUser:user]; /// 发送登录成功的通知 [self postUserDataConfigureCompleteNotification]; [RQ_USER_MANAGER isVipWithComplete:^(NSInteger isVip) {}]; /// 同步本地错题·收藏 // [RQ_UPDATE_LOCALDATA_MANAGER updateLocalWrongAndCollectionWithComplete:nil]; /// 设置别名 // [SBJPushService setAlias]; } /// 退出登录 - (void)logoutUser{ RQUserModel *currentUser = [self currentUser]; currentUser.channel = RQUserLoginChannelTypeDefault; [self saveUser:currentUser]; /// 删除别名 // [SBJPushService deleteAlias]; // // /// 删除token // [self deleteToken]; /// 删除用户数据 [self deleteUser:currentUser]; [RQ_SDJK_DB_MANAGER deleteAllWrongModelsWithComplete:nil]; [RQ_SDJK_DB_MANAGER deleteAllCollectionModelsWithComplete:nil]; [RQ_CACHE_MANAGER removeCacheWithPath:RQ_GET_VipInfo parameters:nil]; } /// 用户信息配置完成 - (void)postUserDataConfigureCompleteNotification{ RQUserModel *user = [self currentUser]; [RQNotificationCenter postNotificationName:RQUserDataConfigureCompleteNotification object:nil userInfo:@{RQUserDataConfigureCompleteUserInfoKey:user}]; } - (void)beginObserveUser { _isObserve = YES; // [[RACSignal combineLatest:@[[RACObserve(self.currentUser, nickName) distinctUntilChanged], [RACObserve(self.currentUser, userName) distinctUntilChanged], [RACObserve(self.currentUser, sex) distinctUntilChanged], [RACObserve(self.currentUser, birthday) distinctUntilChanged], [RACObserve(self.currentUser, carType) distinctUntilChanged], [RACObserve(self.currentUser, email) distinctUntilChanged], [RACObserve(self.currentUser, address) distinctUntilChanged], [RACObserve(self.currentUser, password) distinctUntilChanged]] reduce:^(NSString *nickName, NSString *userName, NSString *sex, NSString *birthday, NSString *carType, NSString *email, NSString *address, NSString *password) { // return self.currentUser; // }] subscribeNext:^(RQUserModel *userModel) { // [self updateUserData]; // }]; } /// 比对本地网络数据 - (void)updateUserData { // [[RQ_HTTP_Service updateUserWithID:self.currentUser.id userName:self.currentUser.userName sex:self.currentUser.sex birthday:self.currentUser.birthday email:self.currentUser.email address:self.currentUser.address nickName:self.currentUser.nickName password:self.currentUser.password photoContent:self.currentUser.photoContent carType:self.currentUser.carType idCard:self.currentUser.idCard] subscribeNext:^(RQUserModel *userModel) { // userModel.channel = RQ_USER_MANAGER.currentUser.channel; // [self willChangeValueForKey:@"user"]; // /// user模型的数据 重置,但是user的 指针地址不变 // [self.currentUser mergeValuesForKeysFromModel:userModel]; // [self didChangeValueForKey:@"user"]; // } error:^(NSError * _Nullable error) { // [MBProgressHUD rq_showErrorTips:error]; // }]; } - (NSString *)headImage { if ([self currentUser].thirdResult) { return RQStringIsNotEmpty(self.currentUser.thirdResult.headimgurl)? self.currentUser.thirdResult.headimgurl : (RQObjectIsNil(self.currentUser.thirdResult.data)? @"" : (RQStringIsNotEmpty(self.currentUser.thirdResult.data.avatar)? self.currentUser.thirdResult.data.avatar : @"")); } else if ([self currentUser].appleUserInfo) { return @""; } else { return @""; } } - (NSString *)nickName { if (self.currentUser) { return self.currentUser.nickName; } else { return @"游客"; } } /// 是否Vip - (void)isVipWithComplete:(VoidBlock_integer)complete { __block BOOL isVerify; if (RQ_USER_MANAGER.isShouldLogin) { [RQ_COMMON_MANAGER checkVersionWithComplete:^(BOOL isOpen) { [[RQ_HTTP_Service getVipInfo] subscribeNext:^(RQGetVipInfoModel *getVipInfoModel) { RQUserModel *userModel = self.currentUser; userModel.userId = getVipInfoModel.userId; userModel.nickName = getVipInfoModel.nickName; userModel.headImage = getVipInfoModel.headImage; [self saveUser:userModel]; //rsa 公钥 NSString *publicKey = [NSString stringWithFormat:@"%@%@%@",@"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCzR04LMmDlwyVRfK+Kgsm/vFMOFyqvGk4QIVC",@"Gj2CKKfhycRExm15N3tKOOouIjl/EU79It45oS+ltJkscvYrJn1zz+1bSoBLelZzJrn7K0NpHF8k", @"bCprsFHd60x+YJ4l8C3SDxfFebo4kqveJzx6JNZKwzFm7LPEO5XB9pEBRwIDAQAB"]; BOOL isApple = RQStringIsEmpty(getVipInfoModel.unionId); // 构造被签名串 NSString *verifyString = [NSString stringWithFormat:@"%@%ld",isApple? @"" : getVipInfoModel.unionId,getVipInfoModel.isVip]; //公钥验签 isVerify = [self verify:verifyString signature:getVipInfoModel.sign withPublivKey:publicKey]; NSLog(@"验签通过了吧------%@", isVerify ? @"YES":@"NO"); if (!isVerify) { [RQ_CACHE_MANAGER removeCacheWithPath:RQ_GET_VipInfo parameters:nil]; } if (complete) { if (isOpen) { complete(2); } else { if (isApple) { RQ_USER_MANAGER.isVip = 3; complete(3); } else { RQ_USER_MANAGER.isVip = getVipInfoModel.isVip; complete(isVerify? RQ_USER_MANAGER.isVip : 0); } } } } error:^(NSError * _Nullable error) { if (isOpen) { complete(2); } else { [MBProgressHUD rq_showErrorTips:error]; if (complete) { RQ_USER_MANAGER.isVip = 0; complete(0); } } }]; }]; } else { complete(0); } } /// 是否Vip - (void)isShouldVipWithComplete:(VoidBlock_integer)complete { [self isVipWithComplete:^(NSInteger isVip) { if (complete) { /// RQ_MARK:不是会员 暂时判定是会员 if (isVip <= 0) { if (RQ_USER_MANAGER.isLogin) { [RQ_Profile_Module showVIPAlertWithComplete:^(BOOL isSuccess) { complete(isSuccess); }]; } else { complete(isVip); } } else { complete(isVip); } } }]; } // verify Signature - (BOOL)verify:(NSString *)content signature:(NSString *)signature withPublivKey:(NSString *)publicKey { SecKeyRef publicKeyRef = [self addPublicKey:publicKey]; if (!publicKeyRef) { NSLog(@"添加公钥失败"); return NO; } NSData *originData = [self sha256:content]; NSData *signatureData = [[NSData alloc] initWithBase64EncodedString:signature options:NSDataBase64DecodingIgnoreUnknownCharacters]; if (!originData || !signatureData) { return NO; } OSStatus status = SecKeyRawVerify(publicKeyRef, kSecPaddingPKCS1SHA256, [originData bytes], originData.length, [signatureData bytes], signatureData.length); if (status ==noErr) { return YES; } else{ NSLog(@"验签失败:%d",status); return NO; } } // digest message with sha1 - (NSData *)sha256:(NSString *)str { const void *data = [str cStringUsingEncoding:NSUTF8StringEncoding]; CC_LONG len = (CC_LONG)strlen(data); uint8_t * md = malloc( CC_SHA256_DIGEST_LENGTH * sizeof(uint8_t) );; CC_SHA256(data, len, md); return [NSData dataWithBytes:md length:CC_SHA256_DIGEST_LENGTH]; } - (SecKeyRef)addPublicKey:(NSString *)pubKey { NSData *data = [[NSData alloc] initWithBase64EncodedString:pubKey options:NSDataBase64DecodingIgnoreUnknownCharacters]; //a tag to read/write keychain storage NSString *tag = @"RSA_PUBLIC_KEY"; NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]]; // Delete any old lingering key with the same tag NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init]; [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass]; [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag]; SecItemDelete((__bridge CFDictionaryRef)publicKey); // Add persistent version of the key to system keychain [publicKey setObject:data forKey:(__bridge id)kSecValueData]; [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass]; [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef]; CFTypeRef persistKey = nil; OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey); if (persistKey != nil){ CFRelease(persistKey); } if ((status != noErr) && (status != errSecDuplicateItem)) { return nil; } [publicKey removeObjectForKey:(__bridge id)kSecValueData]; [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef]; [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef]; [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; // Now fetch the SecKeyRef version of the key SecKeyRef keyRef = nil; status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef); if(status != noErr){ return nil; } return keyRef; } - (void)setTryLookCount:(NSInteger)tryLookCount { NSString *key = [NSString stringWithFormat:@"RQTryLookCountKey-%@",RQ_USER_MANAGER.currentUserId]; [RQ_COMMON_MANAGER saveObjectWithObject:[NSNumber numberWithInteger:tryLookCount] ForKey:key]; } - (NSInteger)tryLookCount { NSString *key = [NSString stringWithFormat:@"RQTryLookCountKey-%@",RQ_USER_MANAGER.currentUserId]; id object = [RQ_COMMON_MANAGER getObjectWithKey:key]; if (RQObjectIsNil(object)) { return 5; } else { NSInteger tryLookCount = [object integerValue]; return tryLookCount; } } #pragma mark - LazyLoad - (RQLoginViewModel *)loginViewModel { if (!_loginViewModel) { _loginViewModel = [[RQLoginViewModel alloc] initWithServices:RQ_APPDELEGATE.services params:nil]; } return _loginViewModel; } @end