Objective-C/Cocoa:如何接受错误的服务器证书?

Objective-C/Cocoa: How do I accept a bad server certificate?

提问人:Mike McMaster 提问时间:8/19/2008 最后编辑:CommunityMike McMaster 更新时间:8/12/2015 访问量:9893

问:

使用 NSURLRequest,我正在尝试访问证书已过期的网站。当我发送请求时,我的 connection:didFailWithError 委托方法被调用,其中包含以下信息:

-1203, NSURLErrorDomain, bad server certificate

我的搜索只找到了一种解决方案:NSURLRequest 中的隐藏类方法:

[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:myHost];

但是,出于显而易见的原因,我不想在生产应用程序中使用私有 API。

有什么建议吗?我是否需要使用 CFNetwork API,如果需要,请回答两个问题:

  • 我可以使用任何示例代码来开始使用?我在网上没有找到任何。
  • 如果我为此使用 CFNetwork,我是否必须完全放弃 NSURL?

编辑:

iPhone OS 3.0 引入了一种支持的方法。更多详细信息,请参阅:如何使用 NSURLConnection 为不受信任的证书使用 SSL 进行连接?

Objective-C 网络

评论


答:

1赞 Matthew Schinckel 8/19/2008 #1

我遇到了同样的问题 - 我正在开发一个SOAP客户端,并且开发服务器有一个“自制”证书。即使使用这种方法,我也无法解决这个问题,因为我没有使用 NSURL,而是(记录不佳且显然被放弃的)WS 方法,并决定暂时(内部)只使用非 SSL 连接。

然而,话虽如此,我想到的问题是,如果你不愿意在生产应用程序中使用私有 API,你是否应该允许访问一个证书狡猾的网站?

我会引用延斯·阿尔夫克(Jens Alfke)的话:

这不仅仅是一个理论上的安全问题。根据
最近的报告,
大约有 25% 的公共 DNS 服务器遭到入侵,即使
用户正确输入域名,也可以将用户引导至网络钓鱼/恶意软件/广告网站。唯一可以保护您
免受这种情况影响的是SSL证书检查。

评论

0赞 Mike McMaster 8/20/2008
有问题的站点位于我们的测试环境中,只能在内部访问。我猜网络管理员太便宜或太懒了,无法为其维护有效的证书。当然,我们的生产环境具有有效的证书。由于在生产中不会启用或不需要此证书躲避功能,因此我可以使用私有 API 进行测试。我仍然更愿意以“正确”的方式去做,因为如果私有 API 被拉扯,我会回到原点。
1赞 David Schlosnagle 8/22/2008 #2

是否可以创建自签名证书并将自定义证书颁发机构添加到受信任的 CA?我不太确定这在 iPhone 上如何工作,但我假设在 Mac OS X 上您会将它们添加到钥匙串中。

您可能也对这篇文章感兴趣 回复:如何处理 NSURLDownload 中的错误证书错误

3赞 user23743 10/19/2008 #3

如果它用于内部服务器进行测试,为什么不直接将测试服务器的证书导入 KeyChain 并设置自定义信任设置呢?

8赞 Louis Gerbarg 10/29/2008 #4

受支持的执行此操作的方法需要使用 CFNetwork。您必须做的是将 kCFStreamPropertySSLSettings 附加到指定 kCFStreamSSLValidatesCertificateChain == kCFBooleanFalse 的流中。下面是一些快速代码,减去检查有效结果,添加清理。完成此操作后,您可以使用 CFReadStreamRead() 获取数据。

CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("http://www.apple.com"), NULL);
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), myURL, kCFHTTPVersion1_1);
CFReadStreamRef myStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);
CFMutableDictionaryRef myDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(myDict, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse);
CFReadStreamSetProperty(myStream, kCFStreamPropertySSLSettings, myDict);    
CFReadStreamOpen(myStream);
0赞 chews 11/22/2008 #5

另一种选择是使用备用连接库。

我是 AsyncSocket 的忠实粉丝,它支持自签名证书

http://code.google.com/p/cocoaasyncsocket/

看一看,我认为它比标准的 NSURLRequests 更强大。

2赞 Mike McMaster 2/4/2010 #6

iPhone OS 3.0 引入了一种受支持的方式,不需要较低级别的 CFNetwork API。更多细节在这里:

如何使用 NSURLConnection 为不受信任的证书使用 SSL 进行连接?