RQUserManager.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. //
  2. // RQUserManager.m
  3. // BuckDriverStudent
  4. //
  5. // Created by 张嵘 on 2019/10/24.
  6. // Copyright © 2019 RONG. All rights reserved.
  7. //
  8. #import "RQUserManager.h"
  9. //#import "RQHTTPService+RQUpdateUser.h"
  10. #import "RQLoginViewModel.h"
  11. #include <CommonCrypto/CommonCrypto.h>
  12. /// 用户信息的名称
  13. static NSString * const RQUserDataFileName = @"senba_empty_user.data";
  14. /// 用户数据配置完成
  15. NSString *const RQUserDataConfigureCompleteNotification = @"RQUserDataConfigureCompleteNotification";
  16. /// 用户数据配置完成,取出userInfo 数据的的key
  17. NSString *const RQUserDataConfigureCompleteUserInfoKey = @"RQUserDataConfigureCompleteUserInfoKey";
  18. @interface RQUserManager ()
  19. /// currentLoginUser
  20. @property (nonatomic, readwrite, strong) RQUserModel *currentUser;
  21. @property (nonatomic, readwrite, assign) BOOL isObserve;
  22. @property (nonatomic, readwrite, strong) RQLoginViewModel *loginViewModel;
  23. @end
  24. @implementation RQUserManager
  25. static id rq_userManager = nil;
  26. #pragma mark - init
  27. + (instancetype)sharedInstance {
  28. static dispatch_once_t onceToken;
  29. dispatch_once(&onceToken, ^{
  30. rq_userManager = [[self alloc] init];
  31. });
  32. return rq_userManager;
  33. }
  34. - (instancetype)init {
  35. if (self = [super init]) {
  36. }
  37. return self;
  38. }
  39. #pragma mark - Private Method
  40. - (void)saveUser:(RQUserModel *)user {
  41. /// 记录用户数据
  42. self.currentUser = user;
  43. /// 保存
  44. BOOL status = [NSKeyedArchiver archiveRootObject:user toFile:RQFilePathFromWeChatDoc(RQUserDataFileName)];
  45. NSLog(@"Save login user data, the status is %@",status?@"Success...":@"Failure...");
  46. if (_currentUser && !_isObserve) {
  47. [self beginObserveUser];
  48. }
  49. }
  50. - (void)deleteUser:(RQUserModel *)user{
  51. /// 删除
  52. self.currentUser = nil;
  53. BOOL status = [RQFileManager removeFile:RQFilePathFromWeChatDoc(RQUserDataFileName)];
  54. NSLog(@"Delete login user data , the status is %@",status?@"Success...":@"Failure...");
  55. self.currentUser = nil;
  56. _isObserve = !status;
  57. self.isVip = 0;
  58. }
  59. - (RQUserModel *)currentUser {
  60. if (!_currentUser) {
  61. _currentUser = [NSKeyedUnarchiver unarchiveObjectWithFile:RQFilePathFromWeChatDoc(RQUserDataFileName) exception:nil];
  62. if (_currentUser && !_isObserve) {
  63. [self beginObserveUser];
  64. }
  65. }
  66. return _currentUser;
  67. }
  68. /// 是否登录
  69. - (BOOL)isLogin {
  70. if (RQObjectIsNil(self.currentUser)) {
  71. return NO;
  72. } else {
  73. return YES;
  74. }
  75. }
  76. /// 是否需要登录
  77. - (BOOL)isShouldLogin {
  78. if (RQObjectIsNil(self.currentUser)) {
  79. if (![RQControllerHelper.currentViewController isKindOfClass:[RQLoginViewController class]]) {
  80. [RQ_APPDELEGATE.services pushViewModel:self.loginViewModel animated:YES];
  81. }
  82. return NO;
  83. } else {
  84. return YES;
  85. }
  86. }
  87. /// 获取当前用户的id
  88. - (NSString *)currentUserId {
  89. if ([self currentUser].thirdResult) {
  90. return RQStringIsNotEmpty(self.currentUser.userId)? self.currentUser.userId : @"";
  91. } else if ([self currentUser].appleUserInfo) {
  92. return [self currentUser].appleUserInfo.sub;
  93. } else {
  94. return @"";
  95. }
  96. }
  97. - (void)loginUser:(RQUserModel *)user{
  98. /// 保存用户
  99. [self saveUser:user];
  100. /// 发送登录成功的通知
  101. [self postUserDataConfigureCompleteNotification];
  102. [RQ_USER_MANAGER isVipWithComplete:^(NSInteger isVip) {}];
  103. /// 同步本地错题·收藏
  104. // [RQ_UPDATE_LOCALDATA_MANAGER updateLocalWrongAndCollectionWithComplete:nil];
  105. /// 设置别名
  106. // [SBJPushService setAlias];
  107. }
  108. /// 退出登录
  109. - (void)logoutUser{
  110. RQUserModel *currentUser = [self currentUser];
  111. currentUser.channel = RQUserLoginChannelTypeDefault;
  112. [self saveUser:currentUser];
  113. /// 删除别名
  114. // [SBJPushService deleteAlias];
  115. //
  116. // /// 删除token
  117. // [self deleteToken];
  118. /// 删除用户数据
  119. [self deleteUser:currentUser];
  120. [RQ_SDJK_DB_MANAGER deleteAllWrongModelsWithComplete:nil];
  121. [RQ_SDJK_DB_MANAGER deleteAllCollectionModelsWithComplete:nil];
  122. [RQ_CACHE_MANAGER removeCacheWithPath:RQ_GET_VipInfo parameters:nil];
  123. }
  124. /// 用户信息配置完成
  125. - (void)postUserDataConfigureCompleteNotification{
  126. RQUserModel *user = [self currentUser];
  127. [RQNotificationCenter postNotificationName:RQUserDataConfigureCompleteNotification object:nil userInfo:@{RQUserDataConfigureCompleteUserInfoKey:user}];
  128. }
  129. - (void)beginObserveUser {
  130. _isObserve = YES;
  131. // [[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) {
  132. // return self.currentUser;
  133. // }] subscribeNext:^(RQUserModel *userModel) {
  134. // [self updateUserData];
  135. // }];
  136. }
  137. /// 比对本地网络数据
  138. - (void)updateUserData {
  139. // [[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) {
  140. // userModel.channel = RQ_USER_MANAGER.currentUser.channel;
  141. // [self willChangeValueForKey:@"user"];
  142. // /// user模型的数据 重置,但是user的 指针地址不变
  143. // [self.currentUser mergeValuesForKeysFromModel:userModel];
  144. // [self didChangeValueForKey:@"user"];
  145. // } error:^(NSError * _Nullable error) {
  146. // [MBProgressHUD rq_showErrorTips:error];
  147. // }];
  148. }
  149. - (NSString *)headImage {
  150. if ([self currentUser].thirdResult) {
  151. 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 : @""));
  152. } else if ([self currentUser].appleUserInfo) {
  153. return @"";
  154. } else {
  155. return @"";
  156. }
  157. }
  158. - (NSString *)nickName {
  159. if (self.currentUser) {
  160. return self.currentUser.nickName;
  161. } else {
  162. return @"游客";
  163. }
  164. }
  165. /// 是否Vip
  166. - (void)isVipWithComplete:(VoidBlock_integer)complete {
  167. __block BOOL isVerify;
  168. if (RQ_USER_MANAGER.isShouldLogin) {
  169. [RQ_COMMON_MANAGER checkVersionWithComplete:^(BOOL isOpen) {
  170. [[RQ_HTTP_Service getVipInfo] subscribeNext:^(RQGetVipInfoModel *getVipInfoModel) {
  171. RQUserModel *userModel = self.currentUser;
  172. userModel.userId = getVipInfoModel.userId;
  173. userModel.nickName = getVipInfoModel.nickName;
  174. userModel.headImage = getVipInfoModel.headImage;
  175. [self saveUser:userModel];
  176. //rsa 公钥
  177. NSString *publicKey = [NSString stringWithFormat:@"%@%@%@",@"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCzR04LMmDlwyVRfK+Kgsm/vFMOFyqvGk4QIVC",@"Gj2CKKfhycRExm15N3tKOOouIjl/EU79It45oS+ltJkscvYrJn1zz+1bSoBLelZzJrn7K0NpHF8k", @"bCprsFHd60x+YJ4l8C3SDxfFebo4kqveJzx6JNZKwzFm7LPEO5XB9pEBRwIDAQAB"];
  178. BOOL isApple = RQStringIsEmpty(getVipInfoModel.unionId);
  179. // 构造被签名串
  180. NSString *verifyString = [NSString stringWithFormat:@"%@%ld",isApple? @"" : getVipInfoModel.unionId,getVipInfoModel.isVip];
  181. //公钥验签
  182. isVerify = [self verify:verifyString signature:getVipInfoModel.sign withPublivKey:publicKey];
  183. NSLog(@"验签通过了吧------%@", isVerify ? @"YES":@"NO");
  184. if (!isVerify) {
  185. [RQ_CACHE_MANAGER removeCacheWithPath:RQ_GET_VipInfo parameters:nil];
  186. }
  187. if (complete) {
  188. if (isOpen) {
  189. complete(2);
  190. } else {
  191. if (isApple) {
  192. RQ_USER_MANAGER.isVip = 3;
  193. complete(3);
  194. } else {
  195. RQ_USER_MANAGER.isVip = getVipInfoModel.isVip;
  196. complete(isVerify? RQ_USER_MANAGER.isVip : 0);
  197. }
  198. }
  199. }
  200. } error:^(NSError * _Nullable error) {
  201. if (isOpen) {
  202. complete(2);
  203. } else {
  204. [MBProgressHUD rq_showErrorTips:error];
  205. if (complete) {
  206. RQ_USER_MANAGER.isVip = 0;
  207. complete(0);
  208. }
  209. }
  210. }];
  211. }];
  212. } else {
  213. complete(0);
  214. }
  215. }
  216. /// 是否Vip
  217. - (void)isShouldVipWithComplete:(VoidBlock_integer)complete {
  218. [self isVipWithComplete:^(NSInteger isVip) {
  219. if (complete) {
  220. /// RQ_MARK:不是会员 暂时判定是会员
  221. if (isVip <= 0) {
  222. if (RQ_USER_MANAGER.isLogin) {
  223. [RQ_Profile_Module showVIPAlertWithComplete:^(BOOL isSuccess) {
  224. complete(isSuccess);
  225. }];
  226. } else {
  227. complete(isVip);
  228. }
  229. } else {
  230. complete(isVip);
  231. }
  232. }
  233. }];
  234. }
  235. // verify Signature
  236. - (BOOL)verify:(NSString *)content signature:(NSString *)signature withPublivKey:(NSString *)publicKey {
  237. SecKeyRef publicKeyRef = [self addPublicKey:publicKey];
  238. if (!publicKeyRef) { NSLog(@"添加公钥失败"); return NO; }
  239. NSData *originData = [self sha256:content];
  240. NSData *signatureData = [[NSData alloc] initWithBase64EncodedString:signature options:NSDataBase64DecodingIgnoreUnknownCharacters];
  241. if (!originData || !signatureData) { return NO; }
  242. OSStatus status = SecKeyRawVerify(publicKeyRef, kSecPaddingPKCS1SHA256, [originData bytes], originData.length, [signatureData bytes], signatureData.length);
  243. if (status ==noErr) { return YES; }
  244. else{ NSLog(@"验签失败:%d",status); return NO; }
  245. }
  246. // digest message with sha1
  247. - (NSData *)sha256:(NSString *)str
  248. {
  249. const void *data = [str cStringUsingEncoding:NSUTF8StringEncoding];
  250. CC_LONG len = (CC_LONG)strlen(data);
  251. uint8_t * md = malloc( CC_SHA256_DIGEST_LENGTH * sizeof(uint8_t) );;
  252. CC_SHA256(data, len, md);
  253. return [NSData dataWithBytes:md length:CC_SHA256_DIGEST_LENGTH];
  254. }
  255. - (SecKeyRef)addPublicKey:(NSString *)pubKey {
  256. NSData *data = [[NSData alloc] initWithBase64EncodedString:pubKey options:NSDataBase64DecodingIgnoreUnknownCharacters];
  257. //a tag to read/write keychain storage
  258. NSString *tag = @"RSA_PUBLIC_KEY";
  259. NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
  260. // Delete any old lingering key with the same tag
  261. NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
  262. [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
  263. [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  264. [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
  265. SecItemDelete((__bridge CFDictionaryRef)publicKey);
  266. // Add persistent version of the key to system keychain
  267. [publicKey setObject:data forKey:(__bridge id)kSecValueData];
  268. [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass];
  269. [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];
  270. CFTypeRef persistKey = nil;
  271. OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
  272. if (persistKey != nil){
  273. CFRelease(persistKey);
  274. }
  275. if ((status != noErr) && (status != errSecDuplicateItem)) { return nil; }
  276. [publicKey removeObjectForKey:(__bridge id)kSecValueData];
  277. [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
  278. [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
  279. [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  280. // Now fetch the SecKeyRef version of the key
  281. SecKeyRef keyRef = nil;
  282. status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
  283. if(status != noErr){
  284. return nil;
  285. }
  286. return keyRef;
  287. }
  288. - (void)setTryLookCount:(NSInteger)tryLookCount {
  289. NSString *key = [NSString stringWithFormat:@"RQTryLookCountKey-%@",RQ_USER_MANAGER.currentUserId];
  290. [RQ_COMMON_MANAGER saveObjectWithObject:[NSNumber numberWithInteger:tryLookCount] ForKey:key];
  291. }
  292. - (NSInteger)tryLookCount {
  293. NSString *key = [NSString stringWithFormat:@"RQTryLookCountKey-%@",RQ_USER_MANAGER.currentUserId];
  294. id object = [RQ_COMMON_MANAGER getObjectWithKey:key];
  295. if (RQObjectIsNil(object)) {
  296. return 5;
  297. } else {
  298. NSInteger tryLookCount = [object integerValue];
  299. return tryLookCount;
  300. }
  301. }
  302. #pragma mark - LazyLoad
  303. - (RQLoginViewModel *)loginViewModel {
  304. if (!_loginViewModel) {
  305. _loginViewModel = [[RQLoginViewModel alloc] initWithServices:RQ_APPDELEGATE.services params:nil];
  306. }
  307. return _loginViewModel;
  308. }
  309. @end