Я пытаюсь создать AuthorizeAttribute, который требует, чтобы HTTPRequest содержал указанный сертификат клиента.
Я нашел хорошую серию постов в блоге по этим вопросам, написанную Андрасом Немесом, здесь:
У меня есть тестовый проект Web API, работающий в VS2015, отладка на сайте, работающем на моем локальном IIS, а не на IIS Express, с настроенным https и настройками SSL, разрешающими сертификаты клиентов.
Я почти уверен, что он настроен правильно, потому что он отлично работает для одного из сертификатов, которые я создал.
Мой атрибут прост:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class KtRequireClientCertAttribute : AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
byte[] cert = HttpContext.Current.Request.ClientCertificate.Certificate;
// if the ClientCertificate is empty, pass null
X509Certificate2 suppliedCert = cert.Any() ? new X509Certificate2(cert) : null;
if (suppliedCert != null && isExpectedCert(suppliedCert)
return;
base.OnAuthorization(actionContext);
}
}
Моя проблема - это нормально работает для одного из сертификатов, которые я создал, следуя инструкциям Андраса, на прошлой неделе.
ClientCertificate.Certificate - это байт [], содержащий 808 элементов, X509Certificate2 работает правильно, и моя логика проверки работает как положено.
Но с каждым сертификатом, который я пытаюсь создать сегодня, HttpContext.Current.Request.ClientCertificate.Certificate пуст.
Я делаю сертификаты таким образом:
MAKECERT.EXE -ic DevRootCertificate.cer -iv DevRootCertificate.pvk -pe -sv testclientcert.pvk -a sha1 -n "CN=testclientcert" -len 2048 -b 01/01/2015 -e 01/01/2030 -sky exchange testclientcert.cer -eku 1.3.6.1.5.5.7.3.2
Простое мое тестовое клиентское приложение:
using (var requestHandler = new WebRequestHandler())
{
var certificate = new X509Certificate2(certificateFile);
requestHandler.ClientCertificates.Add(certificate);
var url = new Uri(baseUrl);
using (var client = new HttpClient(requestHandler){BaseAddress = url})
{
var response = client.GetAsync(endPoint).Result;
response.EnsureSuccessStatusCode();
var content = response.Content.ReadAsStringAsync().Result;
Console.Out.WriteLine(JToken.Parse(content).ToString(Formatting.Indented));
}
}
Вопрос в том, почему один сертификат передается атрибуту, а другой нет?
Дополнительная информация:
Я использую один и тот же клиент на том же сервере, работающем на IIS на моей локальной машине. Веб-сайт настроен на прием, но не требование клиентских сертификатов.
Единственное отличие между тестовым прогоном, который работает, и тем, который не работает, заключается в том, из какого .cer-файла я загружаю сертификат.
Я не уверен, есть ли у работающего сертификата закрытый ключ или нет, но работает файл .cer, а не .pfx.
Файл, который не работал, также был .cer. И я знал, что это не было подписано. Поэтому я создал подписанный сертификат и попытался создать X509Certificate2 () с файлом .pfx. Я получил ошибку 403, даже не попав на сервер.