RQUserManager.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 = NO;
  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:_loginViewModel animated:YES];
  81. }
  82. return NO;
  83. } else {
  84. return YES;
  85. }
  86. }
  87. /// 获取当前用户的id
  88. - (NSString *)currentUserId {
  89. if ([self currentUser].wechatUserInfoModel) {
  90. return [self currentUser].wechatUserInfoModel.unionid;
  91. } else {
  92. return @"";
  93. }
  94. }
  95. - (void)loginUser:(RQUserModel *)user{
  96. /// 保存用户
  97. [self saveUser:user];
  98. /// 发送登录成功的通知
  99. [self postUserDataConfigureCompleteNotification];
  100. [RQ_USER_MANAGER isVipWithComplete:^(BOOL isVip) {}];
  101. /// 设置别名
  102. // [SBJPushService setAlias];
  103. }
  104. /// 退出登录
  105. - (void)logoutUser{
  106. RQUserModel *currentUser = [self currentUser];
  107. currentUser.channel = RQUserLoginChannelTypeDefault;
  108. [self saveUser:currentUser];
  109. /// 删除别名
  110. // [SBJPushService deleteAlias];
  111. //
  112. // /// 删除token
  113. // [self deleteToken];
  114. /// 删除用户数据
  115. [self deleteUser:currentUser];
  116. }
  117. /// 用户信息配置完成
  118. - (void)postUserDataConfigureCompleteNotification{
  119. RQUserModel *user = [self currentUser];
  120. [RQNotificationCenter postNotificationName:RQUserDataConfigureCompleteNotification object:nil userInfo:@{RQUserDataConfigureCompleteUserInfoKey:user}];
  121. }
  122. - (void)beginObserveUser {
  123. _isObserve = YES;
  124. // [[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) {
  125. // return self.currentUser;
  126. // }] subscribeNext:^(RQUserModel *userModel) {
  127. // [self updateUserData];
  128. // }];
  129. }
  130. /// 比对本地网络数据
  131. - (void)updateUserData {
  132. // [[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) {
  133. // userModel.channel = RQ_USER_MANAGER.currentUser.channel;
  134. // [self willChangeValueForKey:@"user"];
  135. // /// user模型的数据 重置,但是user的 指针地址不变
  136. // [self.currentUser mergeValuesForKeysFromModel:userModel];
  137. // [self didChangeValueForKey:@"user"];
  138. // } error:^(NSError * _Nullable error) {
  139. // [MBProgressHUD rq_showErrorTips:error];
  140. // }];
  141. }
  142. - (NSString *)headImage {
  143. if ([self currentUser].wechatUserInfoModel) {
  144. return [self currentUser].wechatUserInfoModel.headimgurl;
  145. } else {
  146. return @"";
  147. }
  148. }
  149. - (NSString *)nickName {
  150. if ([self currentUser].wechatUserInfoModel) {
  151. return [self currentUser].wechatUserInfoModel.nickname;
  152. } else {
  153. return @"驾考学员";
  154. }
  155. }
  156. /// 是否Vip
  157. - (void)isVipWithComplete:(VoidBlock_Bool)complete {
  158. __block BOOL isVerify;
  159. if (RQ_USER_MANAGER.isShouldLogin) {
  160. [self checkVersionWithComplete:^(BOOL isOpen) {
  161. if (isOpen) {
  162. complete(YES);
  163. } else {
  164. [[RQ_HTTP_Service getVipInfo] subscribeNext:^(RQGetVipInfoModel *getVipInfoModel) {
  165. //rsa 公钥
  166. NSString *publicKey = [NSString stringWithFormat:@"%@%@%@",@"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCzR04LMmDlwyVRfK+Kgsm/vFMOFyqvGk4QIVC",@"Gj2CKKfhycRExm15N3tKOOouIjl/EU79It45oS+ltJkscvYrJn1zz+1bSoBLelZzJrn7K0NpHF8k", @"bCprsFHd60x+YJ4l8C3SDxfFebo4kqveJzx6JNZKwzFm7LPEO5XB9pEBRwIDAQAB"];
  167. // 构造被签名串
  168. NSString *verifyString = [NSString stringWithFormat:@"%@%ld",getVipInfoModel.openid,getVipInfoModel.isVip];
  169. //公钥验签
  170. isVerify = [self verify:verifyString signature:getVipInfoModel.sign withPublivKey:publicKey];
  171. NSLog(@"验签通过了吧------%@", isVerify ? @"YES":@"NO");
  172. if (complete) {
  173. RQ_USER_MANAGER.isVip = (BOOL)getVipInfoModel.isVip;
  174. complete(isVerify? RQ_USER_MANAGER.isVip : NO);
  175. }
  176. } error:^(NSError * _Nullable error) {
  177. [MBProgressHUD rq_showErrorTips:error];
  178. if (complete) {
  179. RQ_USER_MANAGER.isVip = NO;
  180. complete(NO);
  181. }
  182. }];
  183. }
  184. }];
  185. } else {
  186. complete(NO);
  187. }
  188. }
  189. /// 是否Vip
  190. - (void)isShouldVipWithComplete:(VoidBlock_Bool)complete {
  191. [self isVipWithComplete:^(BOOL isVip) {
  192. if (complete) {
  193. /// RQ_MARK:不是会员 暂时判定是会员
  194. if (!isVip) {
  195. [RQ_ALERTVIEW_MANAGER rq_ActivateVIPAlertWithComplete:^(BOOL isSuccess) {
  196. complete(isSuccess);
  197. }];
  198. } else {
  199. complete(YES);
  200. }
  201. }
  202. }];
  203. }
  204. - (void)checkVersionWithComplete:(VoidBlock_Bool)complete {
  205. /// 1: open 2: close
  206. // [[RQ_HTTP_Service getConfigKeyWithPath:RQButtonSwitchOriginalPath] subscribeNext:^(NSString *isOpenStr) {
  207. // if ([isOpenStr isEqualToString:@"1"]) {
  208. // complete(YES);
  209. // } else {
  210. // complete(NO);
  211. // }
  212. // } error:^(NSError * _Nullable error) {
  213. // complete(NO);
  214. // }];
  215. }
  216. // verify Signature
  217. - (BOOL)verify:(NSString *)content signature:(NSString *)signature withPublivKey:(NSString *)publicKey {
  218. SecKeyRef publicKeyRef = [self addPublicKey:publicKey];
  219. if (!publicKeyRef) { NSLog(@"添加公钥失败"); return NO; }
  220. NSData *originData = [self sha256:content];
  221. NSData *signatureData = [[NSData alloc] initWithBase64EncodedString:signature options:NSDataBase64DecodingIgnoreUnknownCharacters];
  222. if (!originData || !signatureData) { return NO; }
  223. OSStatus status = SecKeyRawVerify(publicKeyRef, kSecPaddingPKCS1SHA256, [originData bytes], originData.length, [signatureData bytes], signatureData.length);
  224. if (status ==noErr) { return YES; }
  225. else{ NSLog(@"验签失败:%d",status); return NO; }
  226. }
  227. // digest message with sha1
  228. - (NSData *)sha256:(NSString *)str
  229. {
  230. const void *data = [str cStringUsingEncoding:NSUTF8StringEncoding];
  231. CC_LONG len = (CC_LONG)strlen(data);
  232. uint8_t * md = malloc( CC_SHA256_DIGEST_LENGTH * sizeof(uint8_t) );;
  233. CC_SHA256(data, len, md);
  234. return [NSData dataWithBytes:md length:CC_SHA256_DIGEST_LENGTH];
  235. }
  236. - (SecKeyRef)addPublicKey:(NSString *)pubKey {
  237. NSData *data = [[NSData alloc] initWithBase64EncodedString:pubKey options:NSDataBase64DecodingIgnoreUnknownCharacters];
  238. //a tag to read/write keychain storage
  239. NSString *tag = @"RSA_PUBLIC_KEY";
  240. NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
  241. // Delete any old lingering key with the same tag
  242. NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
  243. [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
  244. [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  245. [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
  246. SecItemDelete((__bridge CFDictionaryRef)publicKey);
  247. // Add persistent version of the key to system keychain
  248. [publicKey setObject:data forKey:(__bridge id)kSecValueData];
  249. [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass];
  250. [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];
  251. CFTypeRef persistKey = nil;
  252. OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
  253. if (persistKey != nil){
  254. CFRelease(persistKey);
  255. }
  256. if ((status != noErr) && (status != errSecDuplicateItem)) { return nil; }
  257. [publicKey removeObjectForKey:(__bridge id)kSecValueData];
  258. [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
  259. [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
  260. [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  261. // Now fetch the SecKeyRef version of the key
  262. SecKeyRef keyRef = nil;
  263. status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
  264. if(status != noErr){
  265. return nil;
  266. }
  267. return keyRef;
  268. }
  269. #pragma mark - LazyLoad
  270. - (RQLoginViewModel *)loginViewModel {
  271. if (!_loginViewModel) {
  272. _loginViewModel = [[RQLoginViewModel alloc] initWithServices:RQ_APPDELEGATE.services params:nil];
  273. }
  274. return _loginViewModel;
  275. }
  276. @end