从Azure API管理调用时,X-ARR-ClientCert头中没有证书

从Azure API管理调用时,X-ARR-ClientCert头中没有证书,azure,authentication,azure-web-app-service,azure-api-management,Azure,Authentication,Azure Web App Service,Azure Api Management,我已经使用提供的说明配置了一个Azure网站(带有一个)以使用客户端证书身份验证。总结:您将clientCertEnabled标志设置为true,然后在您的网站上开始请求客户端身份验证证书 很好,但是,现在我想访问发送到服务器的客户端证书。根据MSDN的文章,它应该可以在X-ARR-ClientCert请求头中找到,除非它不是 这意味着任何拥有客户端身份验证证书的人都可以访问我的API,这在我的情况下是不可取的 那么,如何检索客户端发送到Web API的客户端身份验证证书呢 更新1:我实际上是通

我已经使用提供的说明配置了一个Azure网站(带有一个)以使用客户端证书身份验证。总结:您将
clientCertEnabled
标志设置为
true
,然后在您的网站上开始请求客户端身份验证证书

很好,但是,现在我想访问发送到服务器的客户端证书。根据MSDN的文章,它应该可以在
X-ARR-ClientCert
请求头中找到,除非它不是

这意味着任何拥有客户端身份验证证书的人都可以访问我的API,这在我的情况下是不可取的

那么,如何检索客户端发送到Web API的客户端身份验证证书呢

更新1:我实际上是通过调用API。我用客户端身份验证证书配置了APIM,APIM调用我的API时没有问题。但是,当从APIM调用API时,不会设置X-ARR-ClientCert头。当通过Fiddler直接调用时,我确实看到了标题。所以APIM用不同的方式调用我的API

更新2:我再次检查了所有内容并生成了一些日志。首先是我记录的类的相关部分:

protected override async Task<HttpResponseMessage>
    SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
  Trace.TraceInformation("Going to validate client certificate.");

  var x509Certificate2 = request.GetClientCertificate();
  Trace.TraceInformation("Client cert: {0}", x509Certificate2 == null
    ? "<null>"
    : x509Certificate2.Subject);

  try
  {
    var headerKeys = string.Join("|", request.Headers.Select(h => h.Key));
    Trace.TraceInformation("Header keys: {0}", headerKeys);
  ...
直接来自请求的客户端证书和预期的
X-ARR-ClientCert


更新4:最后这碰巧是我自己的错误(当然)。我确信后端的url是
https
,而实际上它是
http
。客户端证书身份验证只在https上工作,因此事后看来,在后端找不到证书是完全有道理的…

我正在联系APIM的工程师,以了解这是如何工作的,并将返回给您。当您的实际API(web应用程序)前面有APIM时,我猜APIM是代理,它将为您处理所有的authN/authZ。因此,只有当此操作成功时,请求才会转到您的API。我猜这就是为什么他们可能只是删除客户端证书,而不是转发它。但是我完全明白为什么客户端证书在web应用程序中仍然有用。

您真的想为API的所有用户管理客户端证书吗?我理解使用客户端证书来确保只有APIM可以直接与您的后端API对话。通常,通过API管理公开API的开发人员使用API密钥来控制对API的访问。使用此方法可以基于不同配置的“产品”应用策略


如果您有管理证书创建和吊销的基础设施,那么这可能是正确的选择,这只是一种不常见的方法。话虽如此,我将调查API管理中有哪些选项可用于提取APIM网关上的证书指纹。

您还需要为Azure托管的API启用客户端证书身份验证-此步骤将确保Azure承载传入请求中的任何X-ARR-ClientCert头

否则,Azure会在X-ARR-ClientCert头到达API之前从Request.Headers中删除它。

注意:此设置仅适用于付费订阅

  • 转到并选择所需的azure帐户
  • 选择订阅->资源组->您的资源组->提供商->microsoft.web->网站->您的网站
  • 从顶部按钮进入读/写模式,进入编辑模式,然后在属性下设置属性“clientCertEnabled”:true

  • 文档:

    感谢您的快速响应!!我不知道它是否真的像你描述的那样有效。我的API实际上需要客户端证书。APIM怎么能绕过这个而不发送证书呢?我的API可以在AWS而不是Azure中运行,那么它将如何工作呢?我对答案很好奇:)@RonaldWildenberg如果APIM成功调用您的后端,那么它正在使用证书。证书在HTTP下面的TCP层传递,因此您不会在请求中看到证书被传递。我猜您看到的X-ARR-ClientCert头是因为ARR从客户端证书中剥离信息并将其复制到头中。我需要确认这一点,但我怀疑当您通过APIM时,您不会通过ARR,因此没有什么可以删除此证书信息。我将研究APIM中存在哪些机制来提取证书信息。我添加了一些我正在使用的代码和结果日志输出。我一直得到的结果是,当APIM调用我的实际API时,我找不到APIM调用我的API必须使用的证书…我已经在使用订阅密钥让开发人员访问产品。问题在于APIM和我的实际API之间。我使用客户端证书根据我的实际API对APIM进行身份验证,效果很好。然而,当任何拥有客户端身份验证证书的人仍然可以访问我的实际API时,这仍然没有多大用处。所以问题是:如何检索APIM在我的实际API中发送的客户端证书。如果你能解释一下,太好了!!:)@罗纳尔德维尔登堡啊哈!现在我明白了。下面是一个委托处理程序,我已经尝试使用
    HttpRequestMessage.GetClientCertificate
    。这个函数总是返回
    null
    。实际的API是Azure网站,因此它位于负载平衡器后面。根据我的理解,客户端证书应该在
    X-ARR-ClientCert
    请求头中。我在我的问题中添加了一些额外的代码和日志输出,证明
    HttpRequestMessage.GetClientCertificate
    对我不起作用。@RonaldWildenberg Ok,这很奇怪。我将尝试重新编程,并让队里的人来看看。
    2015-12-07T08:08:24  PID[8464] Information Going to validate client certificate.
    2015-12-07T08:08:24  PID[8464] Information Client cert: <null>
    2015-12-07T08:08:24  PID[8464] Information Header keys:
      Connection|Host|Max-Forwards|Conf-Organisation-Key|Ocp-Apim-Subscription-Key|
      X-Forwarded-For|X-LiveUpgrade|X-ARR-LOG-ID|DISGUISED-HOST|X-SITE-DEPLOYMENT-ID|
      X-Original-URL
    
    2015-12-07T09:16:45  PID[8464] Information Going to validate client certificate.
    2015-12-07T09:16:45  PID[8464] Information Client cert: CN=rwildenberg@itq.nl
    2015-12-07T09:16:45  PID[8464] Information Header keys:
      Connection|Accept|Accept-Encoding|Accept-Language|Cookie|Host|Max-Forwards|
      User-Agent|Upgrade-Insecure-Requests|DNT|X-LiveUpgrade|X-ARR-LOG-ID|DISGUISED-HOST|
      X-SITE-DEPLOYMENT-ID|X-Original-URL|X-Forwarded-For|X-ARR-SSL|X-ARR-ClientCert
    
    "properties": {
        "name": "my-site",
        "state": "Running",
        "hostNames": [
          "my-site.azurewebsites.net",
          "(string)"
        ],
        ...
        "clientCertEnabled": true,
        ...
     }