我正在尝试为我的一个应用程序设置客户端身份验证,但目前尚未成功。我为我的域名 *.example.com 购买了 Gandi 通配符 SSL 证书,以下是 apache2 服务器上的配置:
在 /etc/apache2/ssl 中我有以下文件:
- example.crt => 证书
- example.csr => 证书签名请求
- example.key => 私钥
- example.pem => 中级证书(gandi 给我的)
这是我的虚拟主机配置:
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerName www.example.com
ServerAdmin [email protected]
DocumentRoot /var/www/example/
ErrorLog ${APACHE_LOG_DIR}/error-https.log
CustomLog ${APACHE_LOG_DIR}/access-https.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/example.crt
SSLCertificateKeyFile /etc/apache2/ssl/example.key
SSLCACertificateFile /etc/apache2/ssl/example.pem
SSLVerifyClient require
SSLVerifyDepth 2
SSLOptions +StdEnvVars
</VirtualHost>
现在,这是我创建客户端证书的过程:
在服务器上:
openssl genrsa -out client.key 2028
openssl req -new -key client.key -out client.csr
openssl x509 -sha256 -req -in client.csr -out client.crt -CA /etc/apache2/ssl/example.crt -CAkey /etc/apache2/ssl/example.key -CAcreateserial -days 1095
为了确保其正常工作,我将“client.*”文件传输到另一台私人服务器上,并使用 curl 创建了这个 php 脚本来测试连接:
<?php
$url = "https://www.example.com/api/client/";
$keyFile = "/etc/apache2/conf/certs/client.key";
$certFile = "/etc/apache2/conf/certs/client.crt";
$certPass = "";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_SSLKEY, $keyFile);
curl_setopt($ch, CURLOPT_SSLCERT, $certFile);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $certPass);
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_HEADER,true);
$result=curl_exec($ch);
curl_close($ch);
var_dump($result);
die();
结果如下:
* Trying IP.AD.DR.RES ...
* TCP_NODELAY set
* Connected to www.example.com (IP.AD.DR.RES) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
* Curl_http_done: called premature == 1
* stopped the pause stream!
* Closing connection 0
bool(false)
这就是我遇到的问题。在 curl 的调试消息中,我可以看到我的证书颁发机构未知。这两行看起来很奇怪:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
因为它与我的虚拟主机配置不匹配。
感谢您的帮助 !
答案1
我确信这个问题已经被回答过很多次了。
这目录文件和路径分析分别是根 CA 文件及其路径由 curl 使用基本上,这包含了您的客户端向外部系统进行身份验证时要检查的所有根 CA 文件。
检查 CA(认证机构)以获取您用于向 Apache 服务器进行身份验证的客户端证书。然后,您需要检查该证书是否在您的 CA 列表(CAfile)中。
答案2
您为 Apache 提供了错误的文件。 应该SSLCertificateFile
指向您的服务器将向任何使用 SSL 的用户提供的证书,因此在您的情况下,它应该是文件example.pem
。SSLCertificateKeyFile
是服务器用于 SSL 通信的密钥文件,因此它应该是证书的密钥example.pem
。 这些与客户端身份验证完全无关。
这SSLCACertificateFile
是应该颁发客户端证书的 CA 证书,因此它应该是example.crt
您情况下的文件。