【问题标题】:How to programmatically add a proxy to an NSURLSession如何以编程方式将代理添加到 NSURLSession
【发布时间】:2023-04-05 15:08:01
【问题描述】:

查看NSURLSessionNSURLSessionConfiguration 的文档,我的印象是我应该使用如下的字典来配置它:

    // Create a dictionary to describe the proxy 
    NSDictionary *proxyDict = @{
        (NSString *)kCFProxyHostNameKey   : @"myProxyHost.com",
        (NSString *)kCFProxyPortNumberKey : @"12345",
        (NSString *)kCFProxyTypeKey       : (NSString*)kCFProxyTypeHTTP
    };

    // Create a configuration that uses the dictionary
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    [configuration setConnectionProxyDictionary:proxyDict];

但是,使用此配置创建的来自NSURLSession 的请求直接连接。

【问题讨论】:

    标签: ios proxy nsurlsession nsurlsessionconfiguration


    【解决方案1】:

    事实证明,您想要的字典键是 Stream 变体,它们是解析为“HTTPProxy”之类的:

    NSString* proxyHost = @"myProxyHost.com";
    NSNumber* proxyPort = [NSNumber numberWithInt: 12345];
    
    // Create an NSURLSessionConfiguration that uses the proxy
    NSDictionary *proxyDict = @{
        @"HTTPEnable"  : [NSNumber numberWithInt:1],
        (NSString *)kCFStreamPropertyHTTPProxyHost  : proxyHost,
        (NSString *)kCFStreamPropertyHTTPProxyPort  : proxyPort,
    
        @"HTTPSEnable" : [NSNumber numberWithInt:1],
        (NSString *)kCFStreamPropertyHTTPSProxyHost : proxyHost,
        (NSString *)kCFStreamPropertyHTTPSProxyPort : proxyPort,
    };
    
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    configuration.connectionProxyDictionary = proxyDict;
    
    // Create a NSURLSession with our proxy aware configuration
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    // Form the request
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.google.com?2"]];
    
    // Dispatch the request on our custom configured session
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:
                                  ^(NSData *data, NSURLResponse *response, NSError *error) {
                                      NSLog(@"NSURLSession got the response [%@]", response);
                                      NSLog(@"NSURLSession got the data [%@]", data);
                                  }];
    
    NSLog(@"Lets fire up the task!");
    [task resume];
    

    【讨论】:

    • 谢谢!一百万次谢谢你!我永远也想不通。如果 Apple 记录这一点,当然会很好。
    • @Jeff - 我试过这个.. 但是从^(NSData *data, NSURLResponse *response, NSError *error) 返回的数据给出了 myProxyHost.com 而不是 www.google.com 的结果,你能帮帮我吗
    • 是否可以使用用户名/密码?如果可能的话怎么做?
    • @AlexanderYatsenko 当我在 2015 年进行这项研究时,答案是坚定的“不”,这很烦人,因为我碰巧知道很快就会提示用户输入凭据。问题是苹果在它自己的层处理代理挑战并且不向您公开任何 API。请参阅该委托进行身份验证挑战,它专门避免代理身份验证。 (也许这是由于存在链式代理。)
    • 如果我有一个带有自动代理配置的 pac 文件,我可以在某处设置这个 pac 文件吗? (在这个文件中我定义了一些服务器应该通过代理访问其他应该直接访问)这可能吗?
    【解决方案2】:

    由于 Jeff 的几个答案键已被弃用,因此我使用这些答案键

    NSMutableDictionary *proxy=[NSMutableDictionary dictionaryWithDictionary:@{(__bridge NSString *)kCFNetworkProxiesHTTPEnable  : @1,  (__bridge NSString *)kCFNetworkProxiesHTTPSEnable : @1}];
    proxy[(__bridge NSString *)kCFNetworkProxiesHTTPProxy] =host;
    proxy[(__bridge NSString *)kCFNetworkProxiesHTTPSProxy]=host;
    proxy[(__bridge NSString *)kCFNetworkProxiesHTTPPort]  =port;
    proxy[(__bridge NSString *)kCFNetworkProxiesHTTPSPort] =port;
    proxy[(__bridge NSString *)kCFProxyUsernameKey]=user;
    proxy[(__bridge NSString *)kCFProxyPasswordKey]=password;
    
    configuration.connectionProxyDictionary=proxy;
    

    【讨论】:

      【解决方案3】:

      如果有人需要这个的 swift 版本:

      斯威夫特 3

      let sessionConfiguration = URLSessionConfiguration.default
      sessionConfiguration.connectionProxyDictionary = [
          kCFNetworkProxiesHTTPEnable as AnyHashable: true,
          kCFNetworkProxiesHTTPPort as AnyHashable: 999, //myPortInt
          kCFNetworkProxiesHTTPProxy as AnyHashable: "myProxyUrlString"
      ]
      let session = URLSession(configuration: sessionConfiguration)
      

      【讨论】:

      • 我在使用它时遇到了麻烦。即使使用了,我的api请求的ip和没有代理使用的一样...
      • 如何在 uiwebview 或 URLSession 上使用会话?
      【解决方案4】:

      kCFProxyPortNumberKey 的值应该是 Int 而不是 String

      【讨论】:

        【解决方案5】:

        Swift 3 扩展

        extension URLSession {
        
            func withProxy(proxyURL: String, proxyPort: Int) -> URLSession {
        
                var configuration = self.configuration
        
                configuration.connectionProxyDictionary = [
                    kCFNetworkProxiesHTTPEnable as AnyHashable : true,
                    kCFNetworkProxiesHTTPPort as AnyHashable : proxyPort,
                    kCFNetworkProxiesHTTPProxy as AnyHashable : proxyURL
                ]
        
                return URLSession(configuration: configuration, delegate: self.delegate, delegateQueue: self.delegateQueue)
            }
        }
        

        用法:

        let session = URLSession().withProxy(proxyURL: "xxxxxx", proxyPort: 8321)
        

        【讨论】:

          【解决方案6】:

          根据之前的所有响应,这适用于 Swift 4,包括 HTTP 和 HTTPS:

          let proxyHost = "127.0.0.1"
          let proxyPort = 8888
          let configuration = URLSessionConfiguration.default
          configuration.connectionProxyDictionary = [
              kCFNetworkProxiesHTTPEnable: true,
              kCFNetworkProxiesHTTPProxy: proxyHost,
              kCFNetworkProxiesHTTPPort: proxyPort,
              kCFNetworkProxiesHTTPSEnable: true,
              kCFNetworkProxiesHTTPSProxy: proxyHost,
              kCFNetworkProxiesHTTPSPort: proxyPort
          ]
          

          proxyHost 应该是主机名,并且不包含任何 URL 方案。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-08-22
            • 2013-12-30
            • 1970-01-01
            • 2013-03-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多