美文网首页iOS开发指南
自动重新获取token的逻辑

自动重新获取token的逻辑

作者: 小苗晓雪 | 来源:发表于2019-01-18 14:59 被阅读14次

    自动帮用户重新获取一下token , 在failure的回调里~

    #import "Network.h"
    #import "AFHTTPSessionManager.h"
    #import "AFNetworkActivityIndicatorManager.h"
    #import "AppData.h"
    #import "AppDelegate.h"
    #import "LoginApi.h"
    #import "LoginViewCtrl.h"   // 登录页
    
    @implementation Network
    
    // AFHTTPSessionManager 单例方法,整个系统使用同一个AFHTTPSessionManager对象:
    + (AFHTTPSessionManager *)manager
    {
        static AFHTTPSessionManager *manager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
            manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:sessionConfiguration];
            //设置自定义userAgent:
            [manager.requestSerializer setValue:[self getUserAgent] forHTTPHeaderField:@"User-Agent"];
            //超时时间(单位秒):
            manager.requestSerializer.timeoutInterval = 5;
        });
        return manager;
    }
    
    #pragma mark - post和get请求方法,最常用的
    //post请求方法-请求尽量使用post请求,防止get请求导致中文乱码
    + (NSURLSessionDataTask *)post:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSInteger statusCode, id responseObject))success failure:(void (^)(NSInteger statusCode))failure finish:(void (^)(void))finish
    {
        AFHTTPSessionManager *manager = [self manager];
        NSMutableDictionary *ps = [NSMutableDictionary dictionaryWithCapacity:5];
        if (parameters)
        {
            [ps addEntriesFromDictionary:parameters];
        }
        //添加session用户名和密码:
        [self addRequiredParams:ps];
        NSLog(@"post path= %@", path);
        NSLog(@"post parameters= %@", ps);
        [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
        NSURLSessionDataTask * dataTask = [manager POST:[self getAbsoluteUrl:path] parameters:ps progress:nil
            success:^(NSURLSessionTask *task, id responseObject){
                
                NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
                NSLog(@"success,statusCode: %ld", (long)statusCode);
                // 请求成功
                if (success)
                {
                    success(statusCode,responseObject);
                }
                if (finish)
                {
                    finish();
                }
            }
            failure:^(NSURLSessionTask *task, NSError *error){
                
                [self task:task parameters:parameters success:success failure:failure finish:finish];
                
            }];
        return dataTask;
        
    }
    
    // get请求:
    + (void)get:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(NSInteger statusCode, id responseObject))success failure:(void (^)(NSInteger statusCode))failure finish:(void (^)(void))finish
    {
        AFHTTPSessionManager *manager = [self manager];
        NSMutableDictionary *ps = [NSMutableDictionary dictionaryWithCapacity:5];
        if (parameters)
        {
            [ps addEntriesFromDictionary:parameters];
        }
        [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
        // 添加tocken:
        [manager GET:[self getAbsoluteUrl:path] parameters:ps progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject){
            
            NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
            NSLog(@"success statusCode: %ld", (long)statusCode);
            // 请求成功:
            if (success)
            {
                kRequestNum = 0;
                success(statusCode,responseObject);
            }
            if (finish)
            {
                finish();
            }
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error){
            
            [self task:task parameters:parameters success:success failure:failure finish:finish];
            
        }];
        
    }
    
    // 标识符:
    static NSInteger kRequestNum = 0;
    
    /**
     *  401判断方法:
     
     */
    
    + (void)task:(NSURLSessionDataTask *)task parameters:(NSDictionary *)parameters success:(void (^)(NSInteger statusCode, id responseObject))success failure:(void (^)(NSInteger statusCode))failure finish:(void (^)(void))finish
    {
        NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
        NSLog(@"failure statusCode: %ld", (long)statusCode);
        // 请求失败:
        if (failure)
        {
            failure(statusCode);
            // statusCode == 401未获取 token 错误:
            if (404 == statusCode)
            {
                kRequestNum++;
                // 如果是第一次请求:
                if (1 == kRequestNum)
                {
                    // 就帮用户重新获取 token:
                    [LoginApi loginWithUserPhone:parameters[@"userPhone"] WithUserPwd:parameters[@"userPwd"] success:success failure:failure finish:finish];
                }
                // 如果不是第一次请求 , 是用户主动发起的第二次请求:
                else
                {
                    // 弹出登录页面并且我还要将 kRequestNum 重置为 0:
                    kRequestNum = 0;
                    // 如果本身的这个请求就是登录页的请求:即: LoginApi响应了 loginWithUserPhone:WithUserPwd:success:failure:finish: 这个方法
                    if ([LoginApi respondsToSelector:@selector(loginWithUserPhone:WithUserPwd:success:failure:finish:)])
                    {
                        return;
                    }
                    // 如果本身的这个网络请求操作不是登录请求:
                    else
                    {
                        // 那就弹出登录页:
                        LoginViewCtrl *loginVc = [[LoginViewCtrl alloc] init];
                        [[AppDelegate getWindow].rootViewController presentViewController:loginVc animated:YES completion:nil];
                    }
                }
            }
            //statusCode == 500等其他错误:
            else
            {
                NSLog(@"statusCode = %ld" , (long)statusCode);
                [Utils showMsg:@"服务器错误 , 网络请求失败"];
            }
        }
        if (finish)
        {
            finish();
        }
    }
    
    
    /**
     *  格式化请求的url
     *
     *  @param url 待格式化的url字符串
     *
     *  @return 加入请求前缀后的url
     */
    + (NSString *)getAbsoluteUrl:(NSString *)url
    {
        NSString  * allUrl = [NSString stringWithFormat:BASE_URL,url];
        return allUrl;
    }
    
    /**
     *  添加用户名及密码
     *
     *  @param parameters 待添加的字典对象
     */
    + (void)addRequiredParams:(NSMutableDictionary *)parameters
    {
        [parameters setObject:[AppData shareInstance].userCode forKey:@"_userCode"];
        [parameters setObject:[AppData shareInstance].pwdMd5 forKey:@"_pwd"];
    }
    
    
    /**
     *  获取自定义的userAgent
     *  格式为:/项目标识/appVersionName_appVersionCode/IOS/手机操作系统版本/手机型号/客户端唯一标识
     *
     *  @return 自定义的userAgent
     */
    + (NSString *)getUserAgent{
        //
        NSString *appFlag    = [[NSBundle mainBundle] objectForInfoDictionaryKey: @"CFBundleName"];
        NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey: @"CFBundleShortVersionString"];
        NSString *osVersion =[NSString stringWithFormat:@"%@ %@",[UIDevice currentDevice].systemName,[UIDevice currentDevice].systemVersion];
        NSString *deviceId   = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
        NSLog(@"%@",[[NSBundle mainBundle] infoDictionary]);
        /**
         * appFlag                      :项目标识
         * appVersion                   :app版本号
         * osVersion                    :ios sdk版本
         * [AppDelegate getDeviceModel] : 型号
         * deviceId                     :设备ID
         */
        return [NSString stringWithFormat:@"/%@/%@/IOS/%@/%@/%@" ,
                appFlag ,
                appVersion ,
                osVersion ,
                [AppDelegate getDeviceModel] ,
                deviceId
                ];
    }
    
    /**
     *  取消当前所有的请求
     */
    + (void)cancelAllRequest
    {
        [[Network manager].operationQueue cancelAllOperations];
    }
    
    @end
    
    

    愿编程让这个世界更美好

    相关文章

      网友评论

        本文标题:自动重新获取token的逻辑

        本文链接:https://www.haomeiwen.com/subject/gmendqtx.html