【问题标题】:Determining Trust With NSURLConnection and NSURLProtectionSpace使用 NSURLConnection 和 NSURLProtectionSpace 确定信任
【发布时间】:2011-06-29 23:47:21
【问题描述】:

我想向 a previously posed question 提出后续问题。我有创建 NSURLRequest/Connection 的代码,运行它并调用用于身份验证的回调方法。具体代码如下:

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] || [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault];
}

-(void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{   

    if ([challenge previousFailureCount] > 0) {
        [[challenge sender] cancelAuthenticationChallenge:challenge];
        NSLog(@"Bad Username Or Password");
        badUsernameAndPassword = YES;
        finished = YES;
        return;
    }

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        if (appDelegate._allowInvalidCert)
        {
            // Go ahead...trust me!
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        else
        {
            TrustGenerator *tg = [[TrustGenerator alloc] init];

            if ([tg getTrust:challenge.protectionSpace])
            {
                // Go ahead...trust me!
                [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
            }
            else {
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
        }
    }
    else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault) {
        NSURLCredential *newCredential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceNone];
        [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
    }
}

我遇到的是带有“[challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]”的“didReceiveAuthenticationChallenge”总是被调用,即使我正在尝试服务器上的证书连接到是受信任的(使用 Verisign 证书进行测试)。所以我看到的是我的应用程序总是提示最终用户信任,即使网站是受信任的。考虑到这是一个人在中间攻击时会发生的事情,等等。我真正想要的是这样的代码:

        if (appDelegate._allowInvalidCert)
        {
            // Go ahead...trust me!
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        else if(The OS trusts the cert on the server)
        {
             [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
        }
        else{...

【问题讨论】:

  • 好帖子!我在哪里可以找到TrustGenerator 代码?

标签: iphone cocoa-touch ios certificate nsurlconnection


【解决方案1】:

所以我花了几天时间研究这个。看起来虽然 NSURLConnection API 无法确定证书是否可信,但安全框架中有一个方法可以处理它。所以这是我想出的代码:

-(void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{   

    if ([challenge previousFailureCount] > 0) {
        [[challenge sender] cancelAuthenticationChallenge:challenge];
        NSLog(@"Bad Username Or Password");
        badUsernameAndPassword = YES;
        finished = YES;
        return;
    }

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {

        SecTrustResultType result;
        //This takes the serverTrust object and checkes it against your keychain
        SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);

        if (appDelegate._allowInvalidCert)
        {
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        //When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server
        else if(result == kSecTrustResultProceed || result == kSecTrustResultConfirm ||  result == kSecTrustResultUnspecified){
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        else
        {
            //Asks the user for trust
            TrustGenerator *tg = [[TrustGenerator alloc] init];

            if ([tg getTrust:challenge.protectionSpace])
            {

                //May need to add a method to add serverTrust to the keychain like Firefox's "Add Excpetion"
                [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
            }
            else {
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
        }
    }
    else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault) {
        NSURLCredential *newCredential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceNone];
        [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
    }
}

【讨论】:

  • +[NSURLCredential credentialForTrust:] 创建一个只为会话保留的凭据,因此它不会像 Firefox 中的附加异常一样。一旦你的应用被杀掉,你就必须重新信任它。
  • 我知道这是一篇旧帖子,但我只是注意到 kSecTrustResultConfirm 已被弃用。
【解决方案2】:

如果结果是kSecTrustResultConfirm,您实际上应该询问用户它是否是受信任的服务器。

【讨论】:

    【解决方案3】:

    如果您拥有 CA 可信证书,上述答案才有效,因为在这种情况下,您使用的是苹果允许的 CA 证书进行验证。

    如果你有自签名证书,你应该使用你自己的 CA 服务器证书来检查它是否有效......

    我发现了一个很好的(有点混乱)here。它也涵盖了两次握手....

    希望对你有所帮助!

    【讨论】:

      猜你喜欢
      • 2012-07-18
      • 2012-12-07
      • 2023-03-09
      • 2011-02-26
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      相关资源
      最近更新 更多