具有自签名SSL和HTTP Basic Auth的AFHTTPRequestOperation(-1012错误)

时间:2014-03-27 17:59:41

标签: ios ssl https afnetworking

我正在尝试通过AFHTTPRequestOperation将照片上传到我的网络服务器。这是我的AFHTTPSessionManager。通过此manager的所有http请求都可以完美运行。

- (AFHTTPSessionManager *)manager
{
    if (_manager == nil) {
        _manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"https://my.domain.com/api/v2"]];
        [_manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"username" password:@"password"];

        AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        policy.allowInvalidCertificates = YES;
        _manager.securityPolicy = policy;
    }
    return _manager;
}

但是当我尝试使用进度处理上传照片时:

- (void)photoSend:(UIImage *)photo
          toUsers:(NSArray *)users
       completion:(CompletionHandler)completion
         progress:(ProgressionHandler)progress
{
    NSDictionary *params = @{
                             @"token":self.token,
                             @"to_usernames":[users componentsJoinedByString:@","],
                             };

    NSString *urlString = [[NSURL URLWithString:@"photo/send" relativeToURL:self.manager.baseURL] absoluteString];
    NSMutableURLRequest *request = [self.manager.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:urlString parameters:params constructingBodyWithBlock:^(id <AFMultipartFormData> formData)
                                    {
                                        [formData appendPartWithFileData:UIImageJPEGRepresentation(photo,0.8)
                                                                    name:@"photo"
                                                                fileName:@"image.jpg"
                                                                mimeType:@"image/jpg"];
                                    } error:nil];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [AFJSONResponseSerializer serializer];
    // Following 2 lines does not make sense. Http headers contains auth data without this code
    //NSURLCredential *credential = [NSURLCredential credentialWithUser:@"login" password:@"password" persistence:NSURLCredentialPersistenceNone];
    //[operation setCredential:credential];

    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
        progress(totalBytesWritten*1.0/totalBytesExpectedToWrite);
    }];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        completion(operation.response, responseObject, operation.error);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        completion(operation.response, nil, error);
    }];

    [self.manager.operationQueue addOperation:operation];
}

我收到以下错误:

  

错误域= NSURLErrorDomain代码= -1012&#34;操作不能   完成。 (NSURLErrorDomain错误-1012。)&#34;的UserInfo = 0x994ff20   {NSErrorFailingURLKey = https://my.domain.com/v2/photo/send,   NSErrorFailingURLStringKey = https://my.domain.com/v2/photo/send}

2 个答案:

答案 0 :(得分:8)

以下是解决方案:

AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
policy.allowInvalidCertificates = YES;
operation.securityPolicy = policy;

因此,HTTP基本身份验证数据由管理员提供给操作,但SSL策略 - 不是。

答案 1 :(得分:1)

AFNetworking中,您可以使用AFSSLPinningMode对安全策略进行更改,因此如果您的服务器未安装SSL,请使用以下代码

let operation = AFHTTPRequestOperation(request: YourMutableRequestObject)

        let policy = AFSecurityPolicy(pinningMode: AFSSLPinningMode.None)
        policy.validatesDomainName = false
        policy.allowInvalidCertificates = true

       operation.securityPolicy = policy

如果您的服务器使用的是证书,则可以使用以下代码

let operation = AFHTTPRequestOperation(request: YourMutableRequestObject)
let policy = AFSecurityPolicy(pinningMode: AFSSLPinningMode.Certificate)
        policy.validatesDomainName = false
        policy.allowInvalidCertificates = true
        operation.securityPolicy = policy

在使用上述代码之前,请确保您已在应用程序包中添加了cer证书,如果不是,您将无法拨打电话,您可以从Web开发人员处获取cer文件或任何向你提供cer的权威。

如果您从Web开发人员那里收到crt文件,则需要使用以下代码使用OpenSSL将其转换为cer

openssl x509 -in apache.crt -out yourCertFileName.cer -outform der

这应该足以进行调用

<强>更新

根据Apple在iOS 9中的新ATS模式,您必须在info.plist文件中提供一些权限。

如果您想要进行不安全的调用,请在下面提供您需要在info.plist内集成的XML(请注意,您不会在此处获取任何自动填充程序,您必须将您的plist视为来源和复制+粘贴下面的内容)

<key>NSAppTransportSecurity</key>
<dict>
 <key>NSExceptionDomains</key>
 <dict>
<key>yourserver.com</key>
<dict>
  <!--Include to allow subdomains-->
  <key>NSIncludesSubdomains</key>
  <true/>
  <!--Include to allow HTTP requests-->
  <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
  <true/>
  <!--Include to specify minimum TLS version-->
  <key>NSTemporaryExceptionMinimumTLSVersion</key>
  <string>TLSv1.1</string>
 </dict>
 </dict>
 </dict>

Apple还提供了一种禁用ATS的方法,下面给出的是同样的XML,但不推荐

<key>NSAppTransportSecurity</key>
<dict>
<!--Include to allow all connections -->
<key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

在我的情况下,因为我的服务器使用自签名证书,我只是将AFSSLPinningMode更改为证书,它按预期工作。

希望这有助于某人