.NET client connecting to ssl Web API

2020-02-17 06:49发布

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:

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:

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?

3条回答
够拽才男人
2楼-- · 2020-02-17 07:21

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.

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

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.

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

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

查看更多
我命由我不由天
3楼-- · 2020-02-17 07:41

Take a look at the C# Ignore certificate errors SO 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.

ServicePointManager
    .ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true;
查看更多
\"骚年 ilove
4楼-- · 2020-02-17 07:41

This worked for me. Just add the following before the call to 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.

查看更多
登录 后发表回答