AFNetworking给请求头添加签名的问题

AFNetworking是iOS开发中非常常见的网络请求框架.基于多次的迭代非常稳定.但是使用不当可能就会有一些小问题

简概:

每次请求均更新AFHTTPRequestSerializer中的sign参数.导致并发时.签名出错.请求失败的问题

细节描述:

项目需要将请求参数进行多次加密获取签名.并且放入到请求头中.就需要在每次请求时都要更新requestSerializer的值.

我们继承AFHTTPSessionManager的JTNetServers是一个单例.里面的参数requestSerializer也是唯一的.

每次请求获取mutableRequest时.即会重新获取HTTPRequestHeaders对象.需要用到requestSerializer中的参数.而该对象取决于self.mutableHTTPRequestHeaders.而从0处可以看出self.mutableHTTPRequestHeaders是会随着外界的设置改变而改变.并发时低概率的情况就会导致:下一个请求设置更改了头文件中的值.会更改上一个请求的httpHeaderField对象.这样就会让上一个请求的sign和请求的参数不匹配而请求失败

  //0
    - (void)setValue:(NSString *)value
    forHTTPHeaderField:(NSString *)field
    {
        dispatch_barrier_async(self.requestHeaderModificationQueue, ^{
            [self.mutableHTTPRequestHeaders setValue:value forKey:field];
        });
    }

    //1
    - (NSDictionary *)HTTPRequestHeaders {
        NSDictionary __block *value;
        dispatch_sync(self.requestHeaderModificationQueue, ^{
            value = [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];
        });
        return value;
    }


    - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
    withParameters:(id)parameters
    error:(NSError *__autoreleasing *)error
    {
        NSParameterAssert(request);
        
        NSMutableURLRequest *mutableRequest = [request mutableCopy];
        //2
        [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
            if (![request valueForHTTPHeaderField:field]) {
                [mutableRequest setValue:value forHTTPHeaderField:field];
            }
        }];
        
        .......
        return mutableRequest;
    }

改进:

给AFURLRequestSerialization添加一个缓存池.将每次请求添加进去.响应的key是以urlString和参数parameters拼接达到唯一性.value则是需要上传时的headerDict.相关代码如下

AFURLRequestSerialization.h相关代码

    /**
     请求header缓存池.
     */
    @property (nonatomic, strong) NSMutableDictionary<NSString *,NSDictionary *> *  httpRequesHeaderMuDict ;

    /**
     将请求头添加到缓存池中
     
     @param key 请求url+parameters参数拼接的字符串
     */
    -(void)reloadCustomHttpRequestHeadersWithKey:(NSString *)key;

    /**
     将请求头从缓存池中删除
     
     @param key 请求url+parameters参数拼接的字符串
     */
    -(void)deleteCustomHttpRequestHeadersWithKey:(NSString *)key;

    AFURLRequestSerialization.m相关代码

    -(NSMutableDictionary<NSString *,NSDictionary *> *)httpRequesHeaderMuDict
    {
        if (!_httpRequesHeaderMuDict) {
            _httpRequesHeaderMuDict = [NSMutableDictionary dictionary];
        }
        return _httpRequesHeaderMuDict;
    }

    -(void)reloadCustomHttpRequestHeadersWithKey:(NSString *)key{
        dispatch_sync(self.requestHeaderModificationQueue, ^{
            NSDictionary * customHttpRequestHeaders = [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];
            [self.httpRequesHeaderMuDict setValue:customHttpRequestHeaders forKey:key];
            NSLog(@"----------------------->%@__%zd",self.httpRequesHeaderMuDict.allKeys,self.httpRequesHeaderMuDict.allKeys.count);
        });
    }

    -(void)deleteCustomHttpRequestHeadersWithKey:(NSString *)key{
        dispatch_sync(self.requestHeaderModificationQueue, ^{
            [self.httpRequesHeaderMuDict removeObjectForKey:key];
            NSLog(@"----------------------->删除->%@__%zd",self.httpRequesHeaderMuDict.allKeys,self.httpRequesHeaderMuDict.allKeys.count);
        });
    }

//将2处的代码更改为4.即从缓存池中.根据唯一的key.取出唯一的requestHeader字典数据做请求

- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
    withParameters:(id)parameters
    error:(NSError *__autoreleasing *)error
    {
        NSParameterAssert(request);
        
        if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
            return [super requestBySerializingRequest:request withParameters:parameters error:error];
        }
        
        NSMutableURLRequest *mutableRequest = [request mutableCopy];
        //4
        NSString * httpRequesKey = [NSString stringWithFormat:@"%@_%@",request.URL,parameters ? parameters : @""];
        NSDictionary * httpRequestHeaders = self.httpRequesHeaderMuDict[httpRequesKey];
        [httpRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
            if (![request valueForHTTPHeaderField:field]) {
                [mutableRequest setValue:value forHTTPHeaderField:field];
            }
        }];
        
        ..........
        return mutableRequest;
    }

最后在请求前添加到缓存池.请求后移除缓存池即可

    NSString * httpRequesKey = [NSString stringWithFormat:@"%@_%@",URLString,parameters ? parameters : @""];
    [self.requestSerializer reloadCustomHttpRequestHeadersWithKey:httpRequesKey];
    __weak typeof(self)weakSelf = self;
    [self POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    [self.requestSerializer deleteCustomHttpRequestHeadersWithKey:httpRequesKey];

转载于:https://www.jianshu.com/p/0659c4c9d5a4

猜你喜欢

转载自blog.csdn.net/weixin_34007879/article/details/91076682