我正在尝试连接到使用 TLS 和客户端证书身份验证的服务器。下面是一个代码片段:
async Task TestClientCertAuth()
{
int iWinInetError = 0;
Uri theUri = new Uri("http://xxx-xxx");
try
{
using (HttpBaseProtocolFilter baseProtocolFilter = new HttpBaseProtocolFilter())
{
// Task<Certificate> GetClientCertificate() displays a UI with all available
// certificates with and returns the user selecter certificate. An
// oversimplified implementation is included for completeness.
baseProtocolFilter.ClientCertificate = await GetClientCertificate();
baseProtocolFilter.AllowAutoRedirect = false;
baseProtocolFilter.AllowUI = false;
using (HttpClient httpClient = new HttpClient(baseProtocolFilter))
using (HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, theUri))
using (HttpResponseMessage httpResponse = await httpClient.SendRequestAsync(httpRequest))
{
httpResponse.EnsureSuccessStatusCode();
// Further HTTP calls using httpClient based on app logic.
}
}
}
catch (Exception ex)
{
iWinInetError = ex.HResult & 0xFFFF;
LogMessage(ex.ToString() + " Error code: " + iWinInetError);
throw;
}
}
// Task<Certificate> GetClientCertificate() displays a UI with all available
// certificates with and returns the user selecter certificate. An
// oversimplified implementation is included for completeness.
private async Task<Certificate> GetClientCertificate()
{
IReadOnlyList<Certificate> certList = await CertificateStores.FindAllAsync();
Certificate clientCert = null;
// Always choose first enumerated certificate. Works so long as there is only one cert
// installed and it's the right one.
if ((null != certList) && (certList.Count > 0))
{
clientCert = certList.First();
}
return clientCert;
}
SendRequestAsync 调用引发 HRESULT 0x80072F7D 异常 - 我相信这意味着 ERROR_INTERNET_SECURITY_CHANNEL_ERROR。服务器证书信任没有问题。客户端证书安装在应用程序本地商店中,我准备使用 CertificateStores.FindAllAsync 检索它。查看 SSL 跟踪,我可以看到没有发送客户端证书。
如果 HttpBaseProtocolFilter.AllowUI 设置为 true,则不会出现上述问题。在这种情况下,SendRequestAsync 调用会导致显示一个 UI,请求同意使用客户端证书。在此对话框中选择“允许”后,我可以看到客户端证书和证书验证消息正在跟踪中发送,并且连接已成功建立。
问题:应用程序代码已经处理了用户的证书选择。我想知道是否有任何方法可以指定同意以编程方式使用客户端证书。因为启用 AllowUI 会导致其他副作用 - 例如,如果服务器重新运行带有 WWW-Authenticate: Basic 标头的 401 HTTP 代码,则基本协议过滤器会弹出它自己的 UI 以接受用户凭据,而不会给调用者机会处理它。想避免上述两种 UI,因为我已经选择了客户端证书并从具有自己 UI 的用户那里获得了凭据。谢谢