我想用PHP写一个gemini服务器。
为了让它在任何情况下都能正常工作,我需要获得客户端证书,如果客户端发送的话。
如果我像这样创建上下文和套接字
$context = stream_context_create(options: [
'ssl' => [
'local_cert' => "path/to/file",
'local_pk' => "path/to/key",
'allow_self_signed' => true,
'verify_peer' => false,
'capture_peer_cert' => true,
],
]);
$socket = stream_socket_server(
address: "tls://localhost:1965",
context: $context
);
字符串
我可以接受这样的关系
$connection = stream_socket_accept(
socket: $socket,
timeout: -1,
peer_name: $peer
);
型
连接可以建立而不会出错。但是当客户端发送证书时,我无法获得它,因为上下文参数中的peer_certificate
没有设置。
$streamParams = stream_context_get_params($resource);
$clientCertificate = $streamParams['options']['ssl']['peer_certificate'] ?? null; # always null
型
当我将verify_peer
设置为true
时,则peer_certificate
被设置为OpenSSLCertificate
对象。但是来自客户端的请求没有证书,导致false
$connection
和以下错误:
Warning: stream_socket_accept(): Could not get peer certificate in [...]
Warning: stream_socket_accept(): Failed to enable crypto in [...]
Warning: stream_socket_accept(): Accept failed: Success in [...]
型
我检查了gemini服务器的python实现,在python中有一个verify_mode
可以设置为CERT_OPTIONAL
。
https://docs.python.org/3/library/ssl.html#ssl.CERT_OPTIONAL
我在PHP中找不到这样的东西。有没有一种方法可以选择性地获取客户端证书?
1条答案
按热度按时间nhaq1z211#
如果
verify_peer
为false,则服务器将不会向客户端请求证书,客户端将不会发送证书,因此无法捕获证书。似乎没有一种方法可以只请求客户端证书并在没有验证的情况下捕获它。还有一个关于此的公开错误-https://bugs.php.net/bug.php?id=80770-近3年未修复。
.在python中有一个verify_mode,您可以将其设置为CERT_OPTIONAL
这并不能解决证书验证的问题。它只是意味着即使客户端请求也不发送证书。但如果客户端发送证书,它必须仍然有效。