OpenSSL“服务器'localhost'需要客户端证书。”:带有localhost apache服务器的iOS 8

Posted

技术标签:

【中文标题】OpenSSL“服务器\'localhost\'需要客户端证书。”:带有localhost apache服务器的iOS 8【英文标题】:OpenSSL "The server 'localhost' requires a client certificate.": iOS 8 with localhost apache serverOpenSSL“服务器'localhost'需要客户端证书。”:带有localhost apache服务器的iOS 8 【发布时间】:2015-10-14 22:54:20 【问题描述】:

我面临 OpenSSL 证书创建和安装相关的问题,或者可能是由于 NSURLConnection,我创建了 OpenSSL 证书 following this。

这是错误的本地化描述

2015-07-24 14:47:32.279 SSLTest[7657:60489] CFNetwork SSLHandshake failed (-9824 -> -9829)
2015-07-24 14:47:32.347 SSLTest[7657:60489] NSURLConnection/CFURLConnection       
HTTP load failed (kCFStreamErrorDomainSSL, -9829)
2015-07-24 14:47:32.576 SSLTest[7657:60350] The server “localhost” requires a client certificate.

每次我收到“服务器 'localhost' 需要客户端证书”错误时。

这是我的 .m

- (void)viewDidLoad

   [super viewDidLoad];

   NSString *url = @"https://localhost/Test.php";

   NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
   [theRequest setHTTPMethod:@"POST"];

   NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
   [theConnection start];


#pragma mark - NSURLConnectionDelegate

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    
    if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust) 
       [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
     else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) 

       SecIdentityRef identity = [self getClientCertificate];
       SecCertificateRef certificateRef;
       SecIdentityCopyCertificate(identity, &certificateRef);
       CFArrayRef certificateArray = CFArrayCreate(NULL, (const void **)certificateRef, 1, NULL);

       NSURLCredential *identityCredential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray *)certificateArray persistence:NSURLCredentialPersistenceForSession];
       [challenge.sender useCredential:identityCredential forAuthenticationChallenge:challenge];
   
 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

   NSLog(@"%@",[error localizedDescription]);


#pragma mark - Certificates

- (SecIdentityRef)getClientCertificate 
    SecIdentityRef identityApp = nil;
    NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
    NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
    CFStringRef password = CFSTR("abcXYZ123");
    const void *keys[] =  kSecImportExportPassphrase ;
    const void *values[] =  password ;
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
    CFRelease(options);
    CFRelease(password);
    if (securityError == errSecSuccess) 
         NSLog(@"Success opening p12 certificate. Items: %ld",       CFArrayGetCount(items));
    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
    identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
 else 
    NSLog(@"Error opening Certificate.");

return identityApp;

我的 httpd.config 看起来像这样(我的本地 mac-mini 系统上有 BITNAMI XAMPP 5.6.8)

Alias /bitnami/ "/Applications/XAMPP/xamppfiles/apache2/htdocs/"
Alias /bitnami "/Applications/XAMPP/xamppfiles/apache2/htdocs"


SSLEngine on
SSLCertificateFile /Applications/XAMPP/xamppfiles/apache2/htdocs/ca.crt
SSLCertificateKeyFile /Applications/XAMPP/xamppfiles/apache2/htdocs/ca_withoutPassword.key

SSLCACertificateFile /Applications/XAMPP/xamppfiles/apache2/htdocs/ca.crt

SSLVerifyClient require

<Directory "/Applications/XAMPP/xamppfiles/apache2/htdocs">
   Options Indexes FollowSymLinks
   AllowOverride All
   Order allow,deny
   Allow from all
</Directory>

我曾尝试使用 SSLCertificateChainFile 和 SSLCACertificateFile,但没有成功。

如果我删除 'SSLVerifyClient require' 并点击服务,那么我会正确收到 authenticationMethod 'NSURLAuthenticationMethodServerTrust' 和服务器响应。

如果我在 .config 文件中添加 'SSLVerifyClient require',则 NSURLConnection 委托方法 'willSendRequestForAuthenticationChallenge' 将调用两次,一次使用 'NSURLAuthenticationMethodServerTrust' strong> 第二次使用 'NSURLAuthenticationMethodClientCertificate' 然后我会得到上述错误。

【问题讨论】:

【参考方案1】:

我认为您的 Apache 设置有误;您将 SSLCACertificateFile 指向您的客户端证书,而客户端证书应该在客户端;您应该将其指向您的 CA 证书。这是用于验证客户端证书的内容。

附带说明,您上面的配置真的不安全。切勿将任何 SSL 证书放在您的公共 htdocs 文件夹中。它们应该放置在只有 root 用户可以读取并且绝对远程用户无法访问的地方。这样,您将自己暴露在最严重的攻击中。

【讨论】:

以上是关于OpenSSL“服务器'localhost'需要客户端证书。”:带有localhost apache服务器的iOS 8的主要内容,如果未能解决你的问题,请参考以下文章

openssl命令详解

OpenSSL升级和php加扩展模板openssl

openssl生成perm文件

php升级openssl扩展,swoole升级openssl扩展,linux安装openssl版本

openssl升级

linux 可以openssl吗