SSL证书检测API:参数详解与工程化落地实践

发布时间:2026/7/17 10:00:31
SSL证书检测API:参数详解与工程化落地实践 适用场景与接口定位部署HTTPS服务的团队常需要批量监控证书有效期、检查通配符覆盖域、验证证书链是否完整。手动逐域查看浏览器地址栏显然低效而这款SSL证书检测API恰好填补了自动化监控的空缺。它通过简单GET请求远程探测目标域名的证书元数据输出颁发者、有效期、SHA-1指纹、远端IP等关键字段并且内置了域名智能剥离与严格校验逻辑减少上游无效请求。典型应用包括证书到期预警——定时调用本API解析expire_days字段当低于阈值时触发告警。CDN或反向代理证书一致性检查——同一域名不同解析IP的证书指纹对比。安全审计——批量检测子公司或合作伙伴域名的证书状态与颁发机构。边缘节点调试——通过remote_address确认实际连接IP辅助排查SNI问题。接口能力边界维度说明请求方法GET接口端点https://v1.apizero.cn/api/ssl鉴权方式可选Bearer TokenHeader:Authorization匿名调用每日30次QPS限制5次/秒缓存策略成功响应缓存6小时无SSL / 连接失败响应缓存30分钟速率限制超出QPS返回429建议配合指数退避重试接口要求域名必须通过RFC 1123校验总长度≤253字符标签长度介于1~63。若传入非法格式如带空格、双点号会直接返回参数错误而不是向上游转发。请求参数详解Query参数参数名必填类型说明示例值domain是string待检测的域名。支持智能剥离自动去除http://、https://、路径、端口、www.前缀。apizero.cn或https://www.apizero.cn/path智能剥离细节输入https://blog.apizero.cn:8080/api?q1会剥离为blog.apizero.cn。www.前缀不会被剥离仅去掉协议、端口、路径。注意通配符域*.apizero.cn不含www.剥离后为*.apizero.cn合法。Header参数参数名必填位置说明示例值Authorization否匿名可用HeaderBearer Token鉴权。格式Bearer sk_live_xxx。匿名调用每日30次。Bearer sk_live_xxxxxxxxxxxxxx注意素材中curl示例使用的Header是X-API-Key但事实卡指定为Authorization。实际以最新文档为准这里我们遵循文档中的Authorization字段并在示例中按文档写法展示。响应示例完整解析{ code: 0, data: { common_name: *.apizero.cn, domain: apizero.cn, domains: [*.apizero.cn, apizero.cn], expire_date: 2026-11-07 17:04:59, expire_days: 184, fingerprint: f4633adfd1cb59185ba094dc3edeef5a8ea26889, is_expired: false, is_ssl: true, issuer: Certum DV TLS G2 R39 CA, issuing_agency: Asseco Data Systems S.A., life_span_days: 198, remote_address: 119.36.225.184:443, signature_algorithm: RSA-SHA256, start_date: 2026-04-22 17:05:00 }, msg: 成功, request_id: abc123def456 }curl 接入示例可复制匿名调用每日30次curl -sS -X GET https://v1.apizero.cn/api/ssl?domainexample.com带鉴权调用推荐用于生产curl -sS \ -X GET \ -H Authorization: Bearer sk_live_你的API密钥 \ https://v1.apizero.cn/api/ssl?domainapizero.cn将sk_live_你的API密钥替换为实际密钥。编程语言接入Rust 示例以下使用reqwest库演示如何发送请求并解析结果。use serde::Deserialize; use std::collections::HashMap; #[derive(Deserialize, Debug)] struct SslResponseData { common_name: OptionString, domain: OptionString, domains: OptionVecString, expire_date: OptionString, expire_days: Optioni64, fingerprint: OptionString, is_expired: Optionbool, is_ssl: bool, issuer: OptionString, issuing_agency: OptionString, life_span_days: Optioni64, remote_address: OptionString, signature_algorithm: OptionString, start_date: OptionString, } #[derive(Deserialize, Debug)] struct SslResponse { code: i32, data: OptionSslResponseData, msg: String, request_id: String, } #[tokio::main] async fn main() - Result(), Boxdyn std::error::Error { let domain apizero.cn; let api_key std::env::var(APIZERO_API_KEY).ok(); let client reqwest::Client::new(); let mut req client .get(https://v1.apizero.cn/api/ssl) .query([(domain, domain)]); if let Some(key) api_key { req req.header(Authorization, format!(Bearer {}, key)); } let resp req.send().await?; let body resp.text().await?; // 注意实际返回外层有一个数组但文档示例直接是对象。需根据真实响应调整解析 // 这里假设直接返回对象文档示例如此 let ssl_resp: SslResponse serde_json::from_str(body)?; if ssl_resp.code 0 { if let Some(data) ssl_resp.data { println!(证书状态: {}, if data.is_ssl { 有SSL } else { 无SSL }); if let Some(days) data.expire_days { println!(到期天数: {}, days); } } } else { eprintln!(请求错误: {} - {}, ssl_resp.code, ssl_resp.msg); } Ok(()) }注意实际响应外层可能是一个数组如素材中[ {...} ]。为了简洁上述代码假设顶层是对象。生产代码应处理数组形式例如let ssl_resp: VecSslResponse ...; let item ssl_resp.into_iter().next().unwrap();。具体以官方文档为准。返回值字段解读字段类型说明codeint业务状态码0表示成功msgstring成功或错误描述request_idstring本次请求的唯一标识用于问题排查dataobject / null当is_sslfalse且无上游错误时data为null其他字段也全为nulldata.is_sslbooltrue表示域名配置了SSL并成功获取证书信息false表示无证书或连接失败data.common_namestring / null证书通用名称CN通常包含通配符data.domainsstring[] / null证书覆盖的所有域名SAN扩展data.expire_datestring / null证书到期UTC时间格式yyyy-MM-dd HH:mm:ssdata.expire_daysint / null距到期天数以当前时间算非证书签发时间data.fingerprintstring / null证书SHA-1指纹40位十六进制data.is_expiredbool / null是否已过期注意字段名is_expired不是is_expiredata.issuerstring / null证书颁发者名称data.issuing_agencystring / null颁发机构CA公司名data.life_span_daysint / null从start_date到expire_date的总天数data.start_datestring / null证书生效UTC时间data.signature_algorithmstring / null签名算法如RSA-SHA256data.remote_addressstring / null实际连接的远端IP:端口对于不含SSL的域名或连接超时所有data内部字段均为null除了is_sslfalse。上游服务异常时返回HTTP 502且code可能非0。常见错误与异常处理HTTP状态码业务code可能原因处理建议2000成功正常解析2001001域名格式不合法检查传入的domain是否符合RFC 1123无空格和非法字符2001002上游连接失败或无证书检查域名是否可达或确认该域名确实没有启用HTTPS400—缺少必填参数domain确认Query中有domain字段401—API Key无效或已过期检查AuthorizationHeader格式确保Bearer后有一个空格429—QPS超限加入重试逻辑间隔至少200ms使用指数退避1s、2s、4s502—上游服务异常记录request_id并稍后重试若持续失败联系服务方三态响应全览is_ssltrue 完整data正常。is_sslfalse data为null所有字段null域名无SSL或无法连接超时、拒绝连接。502 / 上游内部错误不返回200需按状态码处理。工程化注意事项域名剥离测试虽然API自带剥离但在客户端仍建议先对输入做标准化如只传裸域名避免传入https://导致预期外结果。特别地www.不会被剥离如果关心www子域证书应显式传入www.example.com。缓存考虑成功结果缓存6小时意味着同一域名6秒内重复调用不会产生新请求。设计监控调度时建议每6小时轮询一次即可不必低于5分钟。对于无SSL域名缓存30分钟避免短时间内反复扫无效域名。并发限制QPS为5即每秒最多5个请求。批量检测时请加入节流如tokio::time::sleep(Duration::from_millis(200))循环。请求ID记录在日志中记录request_id方便向API提供方反馈异常。指纹校验如果用于证书一致性检测可与本地已知指纹对比注意SHA-1指纹可能在未来浏览器不再信任但API目前仍返回SHA-1。无效null字段当is_sslfalse时所有字段均为null。代码中务必用Option处理避免直接解引用导致panic。参考文档SSL证书检测API官方文档原始文档Markdown