【发布时间】:2017-04-17 22:25:17
【问题描述】:
我正在编写一个 iOS 应用程序,它会访问我们自己的一个 Web 服务器以利用数据。 IIS Web 服务器可公开访问,具有有效的加密证书,并使用 TLS 1.2。据我所知,所有这一切都取决于 App Transport Security。在应用程序中发出 Web 请求时,请求超时,但更有趣的是,此消息记录为“NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806)”。
此 IIS 服务器碰巧接受 X509 客户端证书,用于不涉及移动应用的单独用例。将设置更改为 Ignore 会导致 iOS 应用正常访问服务器。我假设发生超时是因为服务器正在提示应用程序提供客户端证书,并且它不只是响应它没有客户端证书。请注意,我没有将客户端证书设置为 Require。我不确定如何让 iOS 应用程序正常运行,并且在服务器提示客户端证书时继续运行。
有没有办法让它在 iOS 中工作,同时允许 IIS 服务器仍然接受客户端证书?我不想通过向 info.plist 添加 hacky 排除来减少 ATS。
我认为这无关紧要,但我正在使用 C# 在 Xamarin.IOS 中开发 iOS 应用程序。请求是这样的:
using (var client = new WebClient())
{
client.Headers.Add(Constants.RequestHeaders.RequestId, nonce.RequestId.ToString());
client.Headers.Add(Constants.RequestHeaders.Signature, Convert.ToBase64String(nonce.DigitalSignature));
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
var resultJson = client.UploadString("https://foo.com/Api/Register", json);
}
编辑:
我能够通过使用 NuGet 提供的库 ModernHttpClient 来解决此问题。 API 站点接受客户端证书,但不需要它们。在大多数浏览器中,这会导致浏览器一次性提示您指定要使用的证书。但是,在 iOS 中,默认情况下发出程序化 Web 请求不会出现提示(当然),也不会通知服务器它没有要提供的证书。因此,请求只是超时了。使用 ModernHttpClient,我找到了一种将这种行为设置为自动解决的方法。
var handler = new NativeMessageHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
using (var client = new HttpClient(handler))
{ ...
现在它工作正常。我宁愿不必仅仅为了这个非常特定的目的而包含一个库,但它确实有效。也许这个特定的功能可以在不使用库的情况下被提炼成几行代码?无论如何,我很感谢 ModernHttpClient 解决了这个问题;仅仅为了支持 iOS 怪癖而改变服务器行为真的很hacky。
【问题讨论】:
标签: ios ssl iis xamarin client-certificates