Http get request is replayed by NSURLSession when switch network type

最近服务器做了防重放功能,发现iOS有很多命中重放错误,因为我们的请求使用了UUID签名,排除了算法问题

经过排查发现iOS在请求过程中,如果网络发生变化,例如开启和断开vpn,或者开启和关闭WIFI,就会导致系统把正在进行的请求多次重放,这会导致从App的感知来看,请求和响应都只调用了一次,但是服务端却收到了多次

具体操作步骤:

1、开启抓包工具,例如wireshark 2、使用demo代码发送请求(先开启慢速网络,不然速度太快来不及操作): 3、不等请求完成,关闭wifi,这时会切换到蜂窝数据 4、等待请求完成后,通过日志可以看出请求的发送和响应都只进行了一次,但是抓包工具可以看到请求被发送了2次

demo如下:

// Create a URLSession with the default configuration
    NSURLSession *defaultSession = [NSURLSession sharedSession];

    // Setup the request to the URL
    NSTimeInterval ms = [NSDate.date timeIntervalSinceReferenceDate] * 1000;
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://static.fusionbank.com/resource/20240930/8f54352194ac8beecbd5d3f5842b27bb.png?_t=%f",ms]];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
    urlRequest.timeoutInterval = 20;
    // Create dataTask
    NSLog(@"--- request start");
    dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"--- request finish %@", [error localizedDescription]);
            // Handle your response here
            [self.loadingView stopAnimating];
            if (data) {
                UIImage* img = [UIImage imageWithData:data];
                self.imageView.image = img;
            }
        });
    }];
    // Fire the request
    [dataTask resume];

日志如下:

抓包工具显示请求发了2次:

请求和响应情况:

Answered by jolinhe1024 in 814587022

As you can see from the logs, the request was indeed sent twice.

Accepted Answer

As you can see from the logs, the request was indeed sent twice.

Http get request is replayed by NSURLSession when switch network type
 
 
Q