openssl_x509_parse获取validTo_time_t返回1970-01-01的问题求助
解决PHP获取SSL证书过期日期返回1970-01-01的问题
原代码的核心错误是file_get_contents("https://{$website}")获取的是目标网站的页面内容,而非SSL证书本身。openssl_x509_parse无法解析HTML内容,导致返回的证书数据无效,validTo_time_t不存在或为0,最终date函数输出Unix时间戳0对应的1970-01-01。
以下是两种可行的解决方法:
方法一:通过流上下文直接获取证书信息
利用PHP的流上下文配置,在建立HTTPS连接时捕获对等方证书:
<?php $websites = $_POST['websites'] ?? ''; // 过滤空值并清理输入 $websites = array_filter(array_map('trim', explode(',', $websites))); foreach ($websites as $website) { $context = stream_context_create([ 'ssl' => [ 'capture_peer_cert' => true, // 生产环境建议开启以下两项验证,避免风险 'verify_peer' => false, 'verify_peer_name' => false ] ]); $stream = fopen("https://{$website}", 'r', false, $context); if (!$stream) { echo "{$website}: 无法连接站点<br>"; continue; } $params = stream_context_get_params($stream); fclose($stream); if (!isset($params['options']['ssl']['peer_certificate'])) { echo "{$website}: 无法获取证书<br>"; continue; } $cert = openssl_x509_parse($params['options']['ssl']['peer_certificate']); if (!$cert || !isset($cert['validTo_time_t'])) { echo "{$website}: 证书解析失败<br>"; continue; } $expiration = date('Y-m-d', $cert['validTo_time_t']); echo "{$website}: {$expiration}<br>"; } ?>
方法二:调用OpenSSL系统命令获取证书
通过执行openssl s_client命令直接提取证书的过期日期:
<?php $websites = $_POST['websites'] ?? ''; $websites = array_filter(array_map('trim', explode(',', $websites))); foreach ($websites as $website) { // 执行OpenSSL命令获取证书有效期信息 $command = "openssl s_client -connect {$website}:443 </dev/null 2>/dev/null | openssl x509 -noout -dates"; $output = shell_exec($command); if (!$output) { echo "{$website}: 无法获取证书信息<br>"; continue; } // 正则匹配过期日期 preg_match('/notAfter=(.*)/', $output, $matches); if (!isset($matches[1])) { echo "{$website}: 无法解析过期日期<br>"; continue; } $expiration = date('Y-m-d', strtotime($matches[1])); echo "{$website}: {$expiration}<br>"; } ?>
关键注意事项
- 生产环境务必开启
verify_peer和verify_peer_name,防止连接到证书无效或恶意的站点。 - 方法二依赖服务器环境中的OpenSSL命令,需确保PHP有权限执行shell命令(部分主机可能限制)。
- 始终对用户输入做过滤处理,避免命令注入或非法请求风险。
内容的提问来源于stack exchange,提问作者marc louis
相关产品推荐
相关产品推荐

