2

我们使用 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);
            }
4

2 回答 2

3

您可以使用另一个重载的构造函数:

/// <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;
于 2017-06-14T15:33:17.940 回答
0

.net 核心版

Ivan R 的回答让我走上了正确的道路,但对于 .net 核心(此时为 2.2)来说有点不同,因为 WebRequestHandler 在核心中不可用。

在我的情况下,我必须使用 pfx 文件和密码。GetNumberPassedIn不在通用的 Petstore Swagger 模板中,但我正在使用它进行测试。

程序.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();
        }
    }
}

证书信息.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));
        }
    }
}
于 2019-08-09T08:33:01.077 回答