Сертификат клиента доступа в ApiController, размещенный в рабочей роли Azure.

Это может быть повторяющийся вопрос, но я все еще не мог найти ответа, который мог бы решить мою проблему, поэтому опубликую его снова.

У меня есть рабочая роль Azure, и я добавил к ней ApiController с помощью Owin selfhost (см. это для справки).

В моем пользовательском контроллере у меня есть API POST, который пытается выполнить аутентификацию сертификата клиента, извлекая сертификат из объекта запроса, но при развертывании в cemulator azure сертификат всегда имеет значение null.

Вот мой пример кода клиента:

enter code here

общедоступная статическая асинхронная задача GetResponseAsync (WebApiRequestInfo webApiRequestInfo)

{
    if (webApiRequestInfo == null)
    {
        throw new ArgumentNullException("webApiRequestInfo");
    }

    WebRequestHandler requestHandler = null;

    if (webApiRequestInfo.Certificate != null)
    {
        requestHandler = new WebRequestHandler { ClientCertificateOptions = ClientCertificateOption.Manual };
        requestHandler.ClientCertificates.Add(webApiRequestInfo.Certificate);
    }

    using (var client = requestHandler != null
        ? new HttpClient(requestHandler) {BaseAddress = webApiRequestInfo.BaseUrl}
        : new HttpClient {BaseAddress = webApiRequestInfo.BaseUrl})
    {

        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue(webApiRequestInfo.MediaType));

        var method = new HttpMethod(webApiRequestInfo.HttpMethod);

        var request = new HttpRequestMessage(method, webApiRequestInfo.RelativeUrl)
        {
            Content =
                webApiRequestInfo.Content != null
                    ? new StringContent(JsonConvert.SerializeObject(webApiRequestInfo.Content), Encoding.UTF8,
                        "application/json")
                    : null
        };

        var response = await client.SendAsync(request);

        return response;

Код контроллера выглядит так:

[HttpPost]
        public async Task<HttpResponseMessage> GetPackage([FromBody]PackageInfo packageInfo)
        {
            string correlationId = null;
            var logger = TraceLogger<LogData>.Logger;

            try
            {
                if (string.IsNullOrEmpty(packageInfo.Partner))
                {
                    throw new ArgumentException("Partner undefined");
                }

                if (string.IsNullOrEmpty(packageInfo.ServiceEnvironment))
                {
                    throw new ArgumentException("ServiceEnvironment undefined");
                }

                if (string.IsNullOrEmpty(packageInfo.StorageEnvironment))
                {
                    throw new ArgumentException("StorageEnvironment undefined");
                }

                var cert1 = Request.GetClientCertificate();// this is always null
}

Есть ли что-то, что мне не хватает, или это что-то задуманное для эмулятора Azure. Я хотел уточнить это перед развертыванием в облачной службе, чтобы убедиться, что здесь ничего не упущено. Любые предложения по решению этой проблемы будут очень полезны.


person ashish1238    schedule 28.08.2017    source источник
comment
Пожалуйста, проверьте webApiRequestInfo.BaseUrl, это http или https?   -  person Fei Han    schedule 29.08.2017


Ответы (2)


На основе моего теста я могу получить доступ к сертификату клиента в действии контроллера веб-API ASP.NET (который размещен в рабочей роли Azure). Следующий пример кода предназначен для справки.

TestController.cs

public class TestController : ApiController
{
    public HttpResponseMessage Get()
    {
        return new HttpResponseMessage()
        {
            Content = new StringContent("Hello from OWIN!")
        };
    }
    public HttpResponseMessage Get(int id)
    {
        var Thumbprint = Request.GetClientCertificate().Thumbprint.ToString();
        string msg = String.Format("Hello from OWIN (id = {0})", id);
        return new HttpResponseMessage()
        {
            Content = new StringContent(msg)
        };
    }
}

Отправить запрос в консольном приложении

X509Certificate2 certificate = new X509Certificate2(certName, password);

var Thumbprint = certificate.Thumbprint.ToString();

Console.WriteLine($"client certificate Thumbprint: {Thumbprint}");

WebRequestHandler requestHandler = new WebRequestHandler();

requestHandler = new WebRequestHandler { ClientCertificateOptions = ClientCertificateOption.Manual };
requestHandler.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);

requestHandler.ClientCertificates.Add(certificate);


using (var client = new HttpClient(requestHandler))
{   
    HttpResponseMessage response = await client.GetAsync("https://127.0.0.1:9527/test/5");

    if (response.IsSuccessStatusCode)
    {
        string content = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"Received response: {content}");
    }
    else
    {
        Console.WriteLine($"Error, received status code {response.StatusCode}: {response.ReasonPhrase}");
    }
}

Может получить доступ к сертификату клиента в действии контроллера веб-API

введите здесь описание изображения

Вывод консольного приложения

введите здесь описание изображения

person Fei Han    schedule 29.08.2017
comment
Является ли ваш сертификат самоподписанным или он подписан доверенным ЦС, который входит в список доверенных серверов? - person ashish1238; 06.09.2017
comment
В моем тесте я использую самозаверяющий сертификат. - person Fei Han; 08.09.2017

Проблема была связана с органом, выдавшим сертификат, из-за которого IIS отфильтровал сертификат из запроса. Используя правильный сертификат с белым списком CA, все заработало нормально.

person ashish1238    schedule 03.04.2018