C# .NET 客户端连接到 ssl Web API

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15205814/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:29:46  来源:igfitidea点击:

.NET client connecting to ssl Web API

c#asp.net-web-api

提问by TTT

I have a ASP.NET Web API which I'd like to use with ssl. Currently the server is using a self-signed cert, and at this moment both http and https are allowed. I have a very basic test client which works fine for http, but does not work for https. I'd like to know how to modify the client code below so that it will work with https. Currently IE, Firefox, and Chrome can all connect to the Web API using both http and https (with cert warnings), so this makes me believe that I should not have to modify anything on the server, just in the client code. Here's the client code:

我有一个 ASP.NET Web API,我想与 ssl 一起使用。目前服务器使用的是自签名证书,此时 http 和 https 都是允许的。我有一个非常基本的测试客户端,它适用于 http,但不适用于 https。我想知道如何修改下面的客户端代码,以便它可以与 https 一起使用。目前 IE、Firefox 和 Chrome 都可以使用 http 和 https(带有证书警告)连接到 Web API,所以这让我相信我不必修改服务器上的任何内容,只需在客户端代码中即可。这是客户端代码:

static void Main(string[] args)
{
    try
    {
        if (args.Length != 1)
        {
            Console.WriteLine("Please provide a url, and only a url.");
            return;
        }

        var url = new Uri(args[0]);
        var urlAuthority = url.GetLeftPart(UriPartial.Authority);
        var urlPathQuery = args[0].Substring(urlAuthority.Length);
        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri(urlAuthority);
        HttpResponseMessage response = client.GetAsync(urlPathQuery).Result;
        if (response.IsSuccessStatusCode)
            Console.WriteLine(response.Content.ReadAsAsync<string>().Result); // expecting scalar results only
        else
            Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
    }
    catch (Exception ex)
    {
        Exception tempEx = ex;
        while (tempEx != null)
        {
            Console.WriteLine(tempEx.Message);
            tempEx = tempEx.InnerException;
        }
    }
}

When I run the above code with my http url, it works fine. When I change the url to https the following errors are printed:

当我用我的 http url 运行上面的代码时,它工作正常。当我将 url 更改为 https 时,会打印以下错误:

One or more errors occurred.
An error occurred while sending the request.
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
The remote certificate is invalid according to the validation procedure.

One question I have is if the client must manually send a public key to the server so it knows how to send back an encrypted response, or if this happens automatically behind the scenes? And second, now after seeing the last error I'm wondering if I also have to do something else within the client to ignore cert warnings and just trust that this cert is OK to proceed with?

我有一个问题是客户端是否必须手动将公钥发送到服务器,以便它知道如何发回加密的响应,或者这是否在幕后自动发生?其次,现在在看到最后一个错误后,我想知道我是否还必须在客户端中执行其他操作以忽略证书警告并相信该证书可以继续进行?

采纳答案by Oppositional

Take a look at the C# Ignore certificate errorsSO question. I believe you can add a certificate validation handler using ServicePointManager to circumvent certificate validation. It would probably be a good idea to use a signed certificate within your production environment though.

看看C# Ignore certificate errorsSO 问题。我相信您可以使用 ServicePointManager 添加证书验证处理程序来绕过证书验证。不过,在您的生产环境中使用签名证书可能是个好主意。

ServicePointManager
    .ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true;

回答by Davin Tryon

This error message means that the client does not trust the server cert during the SSL handshake. Some browsers are a little more forgiving and give you a "Red bar", but calling from code will result in a 401 and a rejected call.

此错误消息表示客户端在 SSL 握手期间不信任服务器证书。一些浏览器更宽容一点,给你一个“红条”,但从代码调用将导致 401 和拒绝调用。

You do not need to do anything with the client cert settings in IIS (because I assume you are not using a client cert).

您不需要对 IIS 中的客户端证书设置进行任何操作(因为我假设您没有使用客户端证书)。

This exception message is telling you that the self-signed cert chain is rejected when validating on the client. You might be about to get around this by exporting (without the private key), the self-signed cert and installing it on the client machine as a root cert.

此异常消息告诉您在客户端上验证时自签名证书链被拒绝。您可能要通过导出(没有私钥)自签名证书并将其作为根证书安装在客户端计算机上来解决此问题。

If this doesn't work, you need to make a new CA (certificate authority cert) and then generate a new server cert that is signed with the CA. This CA would finally have to be installed on the client machine as a root cert.

如果这不起作用,您需要创建一个新的 CA(证书颁发机构证书),然后生成一个用 CA 签名的新服务器证书。该 CA 最终必须作为根证书安装在客户端计算机上。

This is a good postthat shows the process using makecert and pvk2pfx.

这是一篇很好的帖子,展示了使用 makecert 和 pvk2pfx 的过程。

EDIT:It looks like there might be a wayto configure HttpClientto ignore SSL errors. But, I would strongly suggest that you try to not to have SSL errors from the start.

编辑:看起来可能有一种方法可以配置HttpClient为忽略 SSL 错误。但是,我强烈建议您从一开始就尽量不要出现 SSL 错误。

回答by Rick Arthur

This worked for me. Just add the following before the call to GetAsync.

这对我有用。只需在调用 GetAsync 之前添加以下内容。

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

This will ignore the SSL errors. This is only recommended in an intranet environment or other closed network where server identities can't be forged.

这将忽略 SSL 错误。仅建议在无法伪造服务器身份的内网环境或其他封闭网络中使用此方法。