如何在服务器端读取客户端发送的TLS证书?

87

我正在尝试使用Curl命令调用启用互相认证的服务。

所使用的Curl命令:

curl -k -vvvv \
  --request POST \
  --header "Content-Type: application/json" \
  --cert client.pem:password \
  --key key.pem \
  "https://test.com:8443/testing"

我正在尝试找出以下内容:

  1. 在服务器端,我应该查看哪个HTTP请求头以从HTTP请求中获取客户端证书?

  2. 如果无法从HTTP请求中在服务器端提取客户端证书,那么我可以在HTTP请求中添加自定义请求头并将客户端证书作为该自定义头的值发送吗?如果有人能够提供此方法的示例,那就太好了。

2个回答

202

这是我做的方法:

curl -v \
  --key ./admin-key.pem \
  --cert ./admin.pem \
  https://xxxx/api/v1/

3
这里需要 cacert 吗?这并不能帮助服务器认证客户端的 cert/key 组合;服务器必须已经拥有相关的 cacert (否则,提供密钥、证书和 cacert 与自签名证书没有什么区别,这样做并不能提供任何身份验证对吧?)。我猜它在 服务器 认证中是必需的?主要是想问一下因为我不确定是否完全理解并且想知道是否有误解。 - dwanderson
2
如果在Web服务器使用的CA和客户端证书之间有CA,则可能需要cacert。例如,如果有一家名为X有限公司的公司,其拥有“X有限公司CA”,该公司签署了“X - IT部门”和“X - IT部门”的CA,后者使用“X有限公司CA”的基础CA签署了10个证书,则如果服务器没有“X - IT部门”CA,则客户端需要发送它。 - Rudy Broersma
4
我使用这个答案来调用需要 Mutual TLS 认证才能连接的 API,效果非常好。在我的情况下,我不需要 cacert 参数。 - Rob Carpenter
作者已经解决了这个问题(--cert--key选项在问题中被提及)。问题很清楚:如何在服务器端读取证书数据。这个回答并没有回答这个问题。 - frasertweedale

35
当使用互相认证的TLS时,客户端会发送一个TLS证书。
在互相认证的TLS握手中,TLS客户端证书不会以HTTP头的形式发送。它们作为握手期间交换的TLS消息的一部分由客户端传输,服务器在握手期间验证客户端证书。mTLS握手大体上分为两个部分,客户端验证并接受服务器证书以及服务器验证并接受客户端证书。
如果客户端证书被接受,大多数Web服务器可以配置添加头以传输证书或包含在证书中的信息到应用程序。在ApacheNginx中,环境变量将填充证书信息,这些信息可以用于其他指令以设置头。
作为这种方法的示例,以下Nginx配置片段将验证客户端证书,然后设置SSL_CLIENT_CERT头以将整个证书传递给应用程序。仅在成功验证证书时才会设置此项,因此应用程序可以解析证书并依赖其所承载的信息。
server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/chainedcert.pem;  # server certificate
    ssl_certificate_key /path/to/key;          # server key

    ssl_client_certificate /path/to/ca.pem;    # client CA
    ssl_verify_client on;
    proxy_set_header SSL_CLIENT_CERT $ssl_client_cert;

    location / {
        proxy_pass http://localhost:3000;
    }
}

19
他正在尝试发送证书并询问如何操作。答案解释了服务器如何处理它。哪里有解释正确操作方式的部分? - Akshay Hiremath
1
作者询问如何在服务器端读取证书。我的回答解释了证书不是通过HTTP头从客户端传输到服务器的,但HTTP服务器可以将其暴露给应用程序。我还提供了一个nginx配置示例来实现这一点。 - frasertweedale
我重新措辞和清理了问题,现在这个答案更加合适。我重新措辞了问题,因为提问者已经接受了您的答案。 - Akshay Hiremath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接