Как передать сертификат клиента с помощью клиента 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 всегда null:
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);
}
1 ответ
Вы можете использовать другой перегруженный конструктор:
/// <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;
.net версия ядра
Ответ Ивана Р. привел меня к правильному пути, но он немного отличается для ядра.net (на данный момент 2.2), поскольку WebRequestHandler недоступен в ядре.
В моем случае мне пришлось использовать файл pfx и пароль. GetNumberPassedIn
не входит в общий шаблон Petstore Swagger, но я тестировал именно его.
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));
}
}
}