iOS开发

客户端并发网络请求中Token失效处理方案

2018-04-11  本文已影响12人  蚂蚁牙齿不黑
image.png

近期在做sdk底层网络模块封装的时候碰到一个关于客户端身份认证的问题,拿出来分享一下,可以确定的是我的解决办法并不是最优方案。

1.什么是Token 机制?

token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。 当用户第一次登录后,服务器生成一个Token并将此Token返回给客户端,在以后的请求过程中,需要将该Token作为参数或者放在header里面发送给服务器作为身份验证的一个步骤,无需再次带上用户名和密码,但是服务端每隔一段时间(比如30分钟)就会重新生成Token,这时候客户端再用本地缓存的旧Token去请求就无法通过身份认证,一般状态码都会是401。

下面这段字符串就是一个完整的Token

Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJpc3MiOiJodHRwczovL29wZW4uaml1emhhbmcubmV0IiwiYXVkIjoiaHR0cHM6Ly9vcGVuLmppdXpoYW5nLm5ldC9yZXNvdXJjZXMiLCJleHAiOjE1MjM0MzMyMTcsIm5iZiI6MTUyMzQyOTYxNywiY2xpZW50X2lkIjoicm8uY2xpZW50Iiwic2NvcGUiOlsib2ZmbGluZV9hY2Nlc3MiLCJyZWFkIiwid3JpdGUiXSwic3ViIjoianpkZXZAanpkZXYiLCJhdXRoX3RpbWUiOiIxNTIzNDI5NTgwIiwiaWRwIjoiaWRzcnYiLCJhbXIiOlsicGFzc3dvcmQiXX0.fxTyygfF9rXTYm4tbkLucoF5tm0Zs7O2i_E-2NfOl1x_iy7J_sg-lYxk7UQDoCTHiOJKKAV3cQ3jAymHnzmXrgcdtJQFaYE1qGjVSf3qdELIum2kyoOAkfJ_FHOtpgNxhSNgIdWA42_lKl1QPCBoxQOQyQsqB2cKXVLkC2J-4w7Cysf8cjo4PfSgWYoB64-NrMx1WdD4R0Q0nZ_1-2Ky7sB7495NoOBf7IJ6J-IP12FCOjk6e404rH2ZKNlURjDs9dURuP1k_9x3eOsW0C3sdewMAxpmUzhw278FgZcG30v-UuHaWv0DnGP3Y9jg5ob2ktAqGg8gqF0m0-It6bSz7Q

2.解决办法

image.png

请求A在得知当前缓存的Token失效后就会重新获取服务端的新Token,然后再继续请求A之后的操作

以objective-c代码描述业务逻辑,会用到部分伪代码

//  401代表用户身份认证失败
if(statusCode == 401)
{
       [HttpTool requestWihtUrlString:URL_GetToken params:params success:^(id response, NSUInteger totalCount) {
         // 1.缓存Token
       [[NSUserDefaults standardUserDefaults] setObject:[dataDic objectForKey:@"access_token"] forKey:@"access_token"];
 
      // 2.重点也就在这里了,iOS中AFN帮你拼接的每一个请求实例NSURLSessionDataTask请求过一次便不再可用   所以我们只能从这个实体类中拿到我们的请求信息重新生成一个datatTask重新请求即可,以AFN发起请求为例,GET 请求最简单,只需要把请求的服务器路径取出来就可以了,而POST,PUT,DELETE等需要从请求题body中把二进制转化为我们想要的参数
            NSMutableDictionary *paramDict = [NSMutableDictionary dictionary];
            NSString *urlStr = task.originalRequest.URL.absoluteString;
            NSString *httpMethod = task.originalRequest.HTTPMethod;
            if (![httpMethod isEqualToString:@"GET"])
            {
                NSStringEncoding encoding = [HttpTool sharedManager].requestSerializer.stringEncoding;
                NSData *httpBody = task.originalRequest.HTTPBody;
                NSString *paramStr = [[[NSString alloc] initWithData:httpBody encoding:encoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
                NSArray *keyValues = [paramStr componentsSeparatedByString:@"&"];
                for (NSString *keyValue in keyValues)
                {
                    NSArray *param = [keyValue componentsSeparatedByString:@"="];
                    NSString *key = param.firstObject;
                    NSString *value = param.lastObject;
                    [paramDict setObject:value forKey:key];
                }
            }
            [HttpTool commonRequestWithUrlString:urlStr
                                      method:httpMethod
                                      params:paramDict
                                     success:successBlock
                                     failure:failureBlock];
}

上一篇下一篇

猜你喜欢

热点阅读