【问题标题】:Access Client certificate in ApiController hosted in Azure Worker Role访问 Azure Worker Role 中托管的 ApiController 中的客户端证书
【发布时间】:2018-02-05 08:41:21
【问题描述】:

这可能是一个重复的问题,但我仍然找不到任何可以解决我的问题的答案,所以再次发布。

我有一个 azure worker 角色,并且我使用 Owin selfhost 向它添加了一个 ApiController(请参阅 this 以供参考)。

在我的自定义控制器中,我有一个 POST api,它尝试通过从 Request 对象中提取证书来进行客户端证书身份验证,但是在部署到 azure cemulator 时,证书始终为 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 模拟器设计的东西。我想在部署到云服务之前澄清这一点,以确保这里没有遗漏任何东西。任何解决此问题的建议都会非常有帮助。

【问题讨论】:

  • 请查看webApiRequestInfo.BaseUrl,是http还是https

标签: c# azure azure-worker-roles client-certificates asp.net-apicontroller


【解决方案1】:

问题在于证书颁发机构,因此 IIS 从请求中过滤掉了证书。在 CA 白名单中使用正确的证书开始一切正常。

【讨论】:

    【解决方案2】:

    根据我的测试,我可以在 ASP.NET Web API(托管在 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}");
        }
    }
    

    可以在 Web API 控制器操作中访问客户端证书

    控制台应用输出

    【讨论】:

    • 您的证书是自签名证书还是由作为服务器受信任列表的受信任 CA 签名的?
    • 在我的测试中,我使用的是自签名证书。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-17
    • 2013-01-26
    相关资源
    最近更新 更多