// // 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 = NO; } - (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:_loginViewModel animated:YES]; } return NO; } else { return YES; } } /// 获取当前用户的id - (NSString *)currentUserId { if ([self currentUser].wechatUserInfoModel) { return [self currentUser].wechatUserInfoModel.unionid; } else { return @""; } } - (void)loginUser:(RQUserModel *)user{ /// 保存用户 [self saveUser:user]; /// 发送登录成功的通知 [self postUserDataConfigureCompleteNotification]; [RQ_USER_MANAGER isVipWithComplete:^(BOOL isVip) {}]; /// 设置别名 // [SBJPushService setAlias]; } /// 退出登录 - (void)logoutUser{ RQUserModel *currentUser = [self currentUser]; currentUser.channel = RQUserLoginChannelTypeDefault; [self saveUser:currentUser]; /// 删除别名 // [SBJPushService deleteAlias]; // // /// 删除token // [self deleteToken]; /// 删除用户数据 [self deleteUser:currentUser]; } /// 用户信息配置完成 - (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].wechatUserInfoModel) { return [self currentUser].wechatUserInfoModel.headimgurl; } else { return @""; } } - (NSString *)nickName { if ([self currentUser].wechatUserInfoModel) { return [self currentUser].wechatUserInfoModel.nickname; } else { return @"驾考学员"; } } /// 是否Vip - (void)isVipWithComplete:(VoidBlock_Bool)complete { __block BOOL isVerify; if (RQ_USER_MANAGER.isShouldLogin) { [self checkVersionWithComplete:^(BOOL isOpen) { if (isOpen) { complete(YES); } else { [[RQ_HTTP_Service getVipInfo] subscribeNext:^(RQGetVipInfoModel *getVipInfoModel) { //rsa 公钥 NSString *publicKey = [NSString stringWithFormat:@"%@%@%@",@"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCzR04LMmDlwyVRfK+Kgsm/vFMOFyqvGk4QIVC",@"Gj2CKKfhycRExm15N3tKOOouIjl/EU79It45oS+ltJkscvYrJn1zz+1bSoBLelZzJrn7K0NpHF8k", @"bCprsFHd60x+YJ4l8C3SDxfFebo4kqveJzx6JNZKwzFm7LPEO5XB9pEBRwIDAQAB"]; // 构造被签名串 NSString *verifyString = [NSString stringWithFormat:@"%@%ld",getVipInfoModel.openid,getVipInfoModel.isVip]; //公钥验签 isVerify = [self verify:verifyString signature:getVipInfoModel.sign withPublivKey:publicKey]; NSLog(@"验签通过了吧------%@", isVerify ? @"YES":@"NO"); if (complete) { RQ_USER_MANAGER.isVip = (BOOL)getVipInfoModel.isVip; complete(isVerify? RQ_USER_MANAGER.isVip : NO); } } error:^(NSError * _Nullable error) { [MBProgressHUD rq_showErrorTips:error]; if (complete) { RQ_USER_MANAGER.isVip = NO; complete(NO); } }]; } }]; } else { complete(NO); } } /// 是否Vip - (void)isShouldVipWithComplete:(VoidBlock_Bool)complete { [self isVipWithComplete:^(BOOL isVip) { if (complete) { /// RQ_MARK:不是会员 暂时判定是会员 if (!isVip) { [RQ_ALERTVIEW_MANAGER rq_ActivateVIPAlertWithComplete:^(BOOL isSuccess) { complete(isSuccess); }]; } else { complete(YES); } } }]; } - (void)checkVersionWithComplete:(VoidBlock_Bool)complete { /// 1: open 2: close // [[RQ_HTTP_Service getConfigKeyWithPath:RQButtonSwitchOriginalPath] subscribeNext:^(NSString *isOpenStr) { // if ([isOpenStr isEqualToString:@"1"]) { // complete(YES); // } else { // complete(NO); // } // } error:^(NSError * _Nullable error) { // complete(NO); // }]; } // 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; } #pragma mark - LazyLoad - (RQLoginViewModel *)loginViewModel { if (!_loginViewModel) { _loginViewModel = [[RQLoginViewModel alloc] initWithServices:RQ_APPDELEGATE.services params:nil]; } return _loginViewModel; } @end