Как передать сертификат клиента с помощью клиента AutoRest

Мы используем AutoRest для генерации клиентского кода на основе файлов API Swagger.

Я пытаюсь передать сертификат клиента в API. Но заметил, что сгенерированный клиентский код не принимает WebRequestHandler.

Сгенерированный код выглядит следующим образом:

public MyTestApiV1(Uri baseUri, params DelegatingHandler[] handlers) : this(handlers)
        {
            if (baseUri == null)
            {
                throw new ArgumentNullException("baseUri");
            }
            this.BaseUri = baseUri;
        }

Я чувствую, что здесь что-то упускаю. Кому-нибудь удалось отправить сертификат клиента с помощью AutoRest?

Пробовал это, но webRequestHandler всегда равен нулю:

var webRequestHandler = client.HttpMessageHandlers.First() as WebRequestHandler;
            if (webRequestHandler != null)
            {
                var secretRetrieved = keyVault.GetSecretAsync("my-cert");
                var pfxBytes = Convert.FromBase64String(secretRetrieved.Result);
                // or recreate the certificate directly
                var certificate = new X509Certificate2(pfxBytes);
                webRequestHandler.ClientCertificates.Add(certificate);
            }

person Nil Pun    schedule 05.05.2017    source источник
comment
Вместо этого вы можете попробовать использовать Swagger Codegen для создания клиента C# API и следовать stackoverflow.com/questions/34506086/, чтобы добавить сертификат клиента.   -  person William Cheng    schedule 05.05.2017
comment
Да, это код, сгенерированный autorest codegen.   -  person Nil Pun    schedule 05.05.2017
comment
Верно. Я не знаком с кодом C#, сгенерированным Autorest. Мое предложение - попробовать другой генератор, у которого есть способ прикрепить клиентский сертификат в клиенте C# API.   -  person William Cheng    schedule 05.05.2017


Ответы (2)


Вы можете использовать другой перегруженный конструктор:

/// <summary>
/// Initializes ServiceClient using base HttpClientHandler and list of handlers.
/// </summary>
/// <param name="rootHandler">Base HttpClientHandler.</param>
/// <param name="handlers">List of handlers from top to bottom (outer handler is the first in the list)</param>
protected ServiceClient(HttpClientHandler rootHandler, params DelegatingHandler[] handlers)

ServiceClient — это базовый класс для сгенерированных клиентов. Таким образом, код может выглядеть так:

var secretRetrieved = keyVault.GetSecretAsync("my-cert");
var pfxBytes = Convert.FromBase64String(secretRetrieved.Result);
// or recreate the certificate directly
var certificate = new X509Certificate2(pfxBytes);
WebRequestHandler webRequestHandler = new WebRequestHandler();
webRequestHandler.ClientCertificates.Add(certificate);
var client = new MyTestApiV1(webRequestHandler);
client.BaseUri = baseUri;
person Ivan R.    schedule 14.06.2017

версия .net Core

Ответ Ивана Р привел меня на правильный путь, но он немного отличается для ядра .net (на данный момент 2.2), поскольку WebRequestHandler недоступен в ядре.

В моем случае мне пришлось использовать файл pfx и пароль. GetNumberPassedIn отсутствует в общем шаблоне Swagger для Petstore, но именно его я тестировал.

Program.cs:

using System;
using System.Net.Http;

namespace SimpleApi2.Console
{

    class Program
    {
        static void Main(string[] args)
        {
            var certificate = new CertInfo().GetCertFromPfx(Const.PfxPath, Const.PfxPassword);

            var handler = new HttpClientHandler();
            handler.ClientCertificates.Add(certificate);
            var client = new HttpClient(handler);

            var petStore = new SwaggerPetstore(client, true);
            petStore.BaseUri = new Uri(Const.PublicUrl);
            var result = petStore.GetNumberPassedIn(135, Const.ApiKey);
            System.Console.WriteLine(result.ToString());
            System.Console.ReadKey();
        }
    }
}

CertInfo.cs:

using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Security;

namespace SimpleApi2.Console
{
    class CertInfo
    {
        internal static byte[] ReadFile(string fileName)
        {
            FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            int size = (int)f.Length;
            byte[] data = new byte[size];
            f.Read(data, 0, size);
            f.Close();
            return data;
        }
        public CertInfo() { }

        public X509Certificate2 GetCertFromPfx(string pfxFilePath, string password)
        {
            try
            {

                byte[] rawData = ReadFile(pfxFilePath);
                var passwordAsChars = password.ToCharArray();

                var securePassword = new SecureString();

                foreach (char c in password)
                    securePassword.AppendChar(c);

                securePassword.MakeReadOnly();

                X509Certificate2 x509 = new X509Certificate2(pfxFilePath, password,
                    X509KeyStorageFlags.UserKeySet);

                WriteCertInfo(x509);

                return x509;
            }
            catch (DirectoryNotFoundException)
            {
                System.Console.WriteLine("Error: The directory specified could not be found.");
                throw;
            }
            catch (IOException)
            {
                System.Console.WriteLine("Error: A file in the directory could not be accessed.");
                throw;
            }
            catch (NullReferenceException)
            {
                System.Console.WriteLine("File must be a .cer file. Program does not have access to that type of file.");
                throw;
            }
        }

        private static void WriteCertInfo(X509Certificate2 x509)
        {
            //Print to console information contained in the certificate.
            System.Console.WriteLine("{0}Subject: {1}{0}", Environment.NewLine, x509.Subject);
            System.Console.WriteLine("{0}Issuer: {1}{0}", Environment.NewLine, x509.Issuer);
            System.Console.WriteLine("{0}Version: {1}{0}", Environment.NewLine, x509.Version);
            System.Console.WriteLine("{0}Valid Date: {1}{0}", Environment.NewLine, x509.NotBefore);
            System.Console.WriteLine("{0}Expiry Date: {1}{0}", Environment.NewLine, x509.NotAfter);
            System.Console.WriteLine("{0}Thumbprint: {1}{0}", Environment.NewLine, x509.Thumbprint);
            System.Console.WriteLine("{0}Serial Number: {1}{0}", Environment.NewLine, x509.SerialNumber);
            System.Console.WriteLine("{0}Friendly Name: {1}{0}", Environment.NewLine, x509.PublicKey.Oid.FriendlyName);
            System.Console.WriteLine("{0}Public Key Format: {1}{0}", Environment.NewLine, x509.PublicKey.EncodedKeyValue.Format(true));
            System.Console.WriteLine("{0}Raw Data Length: {1}{0}", Environment.NewLine, x509.RawData.Length);
            System.Console.WriteLine("{0}Certificate to string: {1}{0}", Environment.NewLine, x509.ToString(true));
        }
    }
}
person Badgerspot    schedule 09.08.2019