我使用以下代码并获得HttpRequestException
例外:
using (var handler = new HttpClientHandler())
{
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2(@"C:\certificates\cert.pfx"));
// I also tried to add another certificates that was provided to https access
// by administrators of the site, but it still doesn't work.
//handler.ClientCertificates.Add(new X509Certificate2(@"C:\certificates\cert.crt"));
//handler.ClientCertificates.Add(new X509Certificate2(@"C:\certificates\cert_ca.crt"));
using (var client = new HttpClient(handler))
{
var response = client.GetAsync("https://someurl.com/api.php?arg1=some&arg2=test").GetAwaiter().GetResult();
// ^ HttpRequestException: An error occurred while sending the request.
}
}
例外:
WinHttpException: A security error occurred
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Net.Http.WinHttpHandler+<StartRequest>d__105.MoveNext()
HttpRequestException: An error occurred while sending the request.
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult()
System.Net.Http.HttpClient+<FinishSendAsync>d__58.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
MyApp.Web.Controllers.HomeController.Test() in HomeController.cs
var response = client.GetAsync("https://someurl.com/api.php?arg1=some&arg2=test").GetAwaiter().GetResult();
lambda_method(Closure , object , Object[] )
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__27.MoveNext()
我还尝试将相同的证书导出到Windows证书存储区并通过谷歌浏览器使用它并且工作正常(浏览器要求我确认已安装的证书,然后加载资源)。
为什么它不能在我的代码中工作?
已更新
我还尝试添加回调来验证证书:
handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) =>
{
// I set a breakpoint to this point but it is not catched.
return true;
};
UPDATED2
证书使用SHA-1。在support for SHA1 certs is being withdrawn的评论中提到了Neil Moss。 如果这是它无法正常工作的真正原因,是否有解决方法?
解
谢谢Neil Moss的解决方案。他建议使用Tls标志进行SSL协议。
handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
但它还需要以下内容:
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
我加上这个之后就可以了。
答案 0 :(得分:17)
根据this SO post,您必须使用ServicePointManager启用TLS1.2。
System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls; // comparable to modern browsers
另外值得注意的是,ServicePointManager.SecurityProtocols属性的MSDN documentation生成了这个语句:
.NET Framework 4.6包含一个阻止的新安全功能 用于连接的不安全密码和散列算法。
这表明某种形式的SHA1阻止可能到位。
答案 1 :(得分:3)
这是一个非常有用的文档。对于ASP.NET Core 2.0,答案应用如下(结果成功):
using (var handler = new HttpClientHandler())
{
handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
using (HttpClient client = new HttpClient(handler))
{
string requestObjJson = requestObj.ToJson();
var address = new Uri($"https://yourcompany.com/");
string token = GetToken();
client.BaseAddress = address;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var contentData = new StringContent(requestObjJson, System.Text.Encoding.UTF8, "application/json");
using (var response = await client.PostAsync("yourcompany/new-employee", contentData))
{
var content = response.Content.ReadAsStringAsync();
var taskResult = content.Result;
JObject resultObj = JObject.Parse(taskResult);
return resultObj;
}
}
}
答案 2 :(得分:0)
根据documentation,最好使用无。 无“允许操作系统选择要使用的最佳协议,并阻止不安全的协议。除非您的应用有特定理由不这样做,否则您应该使用此字段”