尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

leak-check API实战:三步实现邮箱、手机号、身份证泄漏检测

发布时间:2026/9/26 5:14:05

资讯中心
01
ARTICLE

leak-check API实战:三步实现邮箱、手机号、身份证泄漏检测

leak-check API实战:三步实现邮箱、手机号、身份证泄漏检测
你有没有过这样的经历某个平台突然流传出“百万用户数据泄露”的截图底下一群人晒出自己的手机号和邮箱点开一看自己的账号居然也在里面。这时候你最想干的事就是确认自己到底暴露了多少信息、哪些平台的数据被拖了、手机号、邮箱、身份证有没有被卷进去。leak-check API 就是用来解决这个问题的工具它把散落在公开渠道的泄漏样本数据整理成可查询的接口用简单的 HTTP 请求就能检测三类敏感信息是否出现在已知泄漏记录中。这篇博文不绕弯子直接用三步带你跑通 leak-check API第一步准备密钥和请求协议第二步写出邮箱、手机号、身份证三类检测的完整代码第三步处理结果、批量任务和文档里不会写的坑。适合谁看想做账号安全自查的个人用户、需要批量排查企业客户数据是否泄露的 IT 人员、安全工程师以及所有想系统了解泄漏检测 API 工作方式的人。1. 这三个数据维度到底在查什么leak-check API的产品逻辑很多人以为“泄漏检测”就是一个黑盒丢一个手机号进去出来一句“泄露了/没泄露”。真上手之后会发现邮箱、手机号、身份证这三个维度的检测逻辑差异很大搞清楚它们分别是怎么工作的后面写代码、判读结果才不会跑偏。1.1 邮箱检测数据库匹配和指纹比对邮箱是目前泄漏数据里最常见的主键。不管是电商网站、社区论坛还是各种业务系统被拖库导出的用户表里基本都有邮箱字段。leak-check 类服务做的事是把历年来公开流传的泄漏样本收集、清洗、建立索引再存成一套可检索的数据库。你查询一个邮箱时服务端做的是字符串匹配——先做归一化处理再去样本库比对命中就返回该邮箱出现在哪些泄漏事件中、首次发现时间和最近出现时间。归一化这个细节特别值得注意。同一个邮箱可能有多种写法比如User.NametagExample.com和usernameexample.com可能指向同一个人。服务商一般有自己的归一化规则但你在传参时也最好自己做一遍简单清洗去掉首尾空格、全部转小写这样能减少不少无效查询。有一点要提醒这类接口通常不会直接返回泄漏库中的密码明文。正规服务商只告诉你“命中/未命中/风险等级”以及命中的事件名称不会把库里对应密码原文返回给你。原因很简单把别人的密码原文二次分发是违法的服务商自己也担不起这个责任。所以对接时如果看到某个“泄漏检测 API”承诺返回密码明文基本可以判定不合规趁早远离。1.2 手机号检测与邮箱检测的差异手机号检测的原理和邮箱类似也是拿手机号去样本库匹配但有几个坑跟邮箱不一样。首先手机号比邮箱的隐私敏感度高得多。邮箱可能是工作号、注册专用号泄露后无非是收垃圾邮件但手机号泄露之后意味着短信轰炸、精准诈骗、社工攻击都找上门。所以正经服务商对手机号查询的管控更严格有的要求企业资质有的会在响应里强制脱敏比如返回138****5678而不是完整号码。其次手机号匹配的准确性受号码段变化影响。携号转网、虚拟运营商号段、170/171 这类号码在一些老样本库里可能没有覆盖或者被错误标记。这意味着命中结果相对保守没查到不代表绝对安全只能代表“在当前样本库中未发现”。反过来如果查到了基本就是实锤因为手机号是强标识不太可能因为格式差异导致误报。还有一个实操经验批量查手机号时建议在脚本里前置一步格式清洗统一去掉86前缀、空格和横线存成 11 位纯数字再提交。别小看这一步很多服务商的样本库做得糙你传一个带空格或者带国家码的号码过去它匹配不上返回“未命中”容易误导判断。1.3 身份证检测实名信息核验的特殊性身份证这个维度最特殊因为它不是“能不能换”的问题——邮箱可以换、手机号可以换身份证号是伴随终身的一旦泄露没有任何挽回余地。所以身份证检测的价值比前两者更大但能做的事情也要分清楚。leak-check 类接口能回答的问题是这个身份证号是否出现在已知的泄漏样本中。它不能回答的是“这个身份证号对应的姓名是谁”“这个身份证号和某个人名是否匹配”。后一类属于实名核验需要的是身份证二要素姓名身份证号或三要素姓名身份证号手机号核验接口通常由运营商或持牌数据服务商提供个人开发者申请门槛高很多还需要企业资质。所以一个完整的身份证风险排查闭环通常是两步第一步用 leak-check API 查身份证号是否在历史泄漏样本中第二步如果命中再配合实名核验服务确认当前这个身份证对应的实名信息是否已经跟某个手机号、某个姓名绑定。两步是不同接口别指望一个 API 全搞定。这一点我在对接时经常遇到有人理解偏差以为身份证检测就是查“这个号是谁的”那是实名核验的事不是泄漏检测的事。2. 第一步密钥、鉴权与第一个请求不管后面写多少代码第一步都是先拿到 API 密钥把请求协议跑通。这一步听起来简单但我在实际项目里见过太多人栽在环境准备上。2.1 注册、密钥获取与额度确认大多数 leak-check 服务商都提供自助注册。注册之后进入控制台能找到 API Key 或者 Access Token。有些服务商还区分测试密钥和正式密钥测试密钥有严格的调用次数限制正式密钥按套餐计费。拿密钥之后第一件事不是写代码而是看文档里的两页接口鉴权方式和限流规则。鉴权方式常见的就几种请求头带Authorization: Bearer KEY、请求头带X-Api-Key: KEY、或者要求在 URL 里拼?api_keyKEY。我建议优先选择支持 Header 鉴权的服务商因为 API Key 拼在 URL 里有被网关日志、代理服务记录下来的风险而 Header 里的鉴权信息被默认脱敏的概率更大。这属于网络安全的基本功谁做谁知道。限流规则重点看三件事每秒请求上限QPS、每日总调用量、超过限制之后的返回码。大多数服务商限流返回 429也有的返回 403这个字段直接决定了你后面的重试策略。拿到密钥后我习惯先写一个最小请求脚本打一次真实接口确认返回结构和文档描述一致再往下走。别嫌多这一步文档和真实行为不一致的情况我碰到不止一次。2.2 请求协议与最小可用的查询示例下面这个示例基于常见 leak-check API 的设计约定编写。域名、端点路径和字段名是示例真实服务商可能用/api/v1/lookup、X-Api-Key头等不同设计一切以官方文档为准。先看一个最小查询用 curl 查一个邮箱curl -X POST https://api.leak-check.example/v1/check \ -H Authorization: Bearer YOUR_API_KEY \ -H Content-Type: application/json \ -d {type:email,value:userexample.com}这里用 POST 而不是 GET是有讲究的。GET 请求的查询参数会完整出现在访问日志、代理缓存和浏览器历史里也就是说你查的手机号、邮箱很可能被基础设施记录。POST 把请求体放在 Body 里虽然不等于绝对安全但至少不会随便进 URL 日志。对于泄漏检测这种本身就极度敏感的接口选择 POST 是更稳的做法。提示示例中的 API 域名、端点路径和字段名是通用写法实际服务商的接口可能叫/api/v1/search、鉴权头可能用X-Api-Key请以官方文档为准。对应的 Python 请求长这样import requests API_URL https://api.leak-check.example/v1/check API_KEY YOUR_API_KEY def check_value(data_type: str, value: str) - dict: resp requests.post( API_URL, headers{ Authorization: fBearer {API_KEY}, Content-Type: application/json, }, json{type: data_type, value: value}, timeout10, ) resp.raise_for_status() return resp.json() result check_value(email, userexample.com) print(result)跑通这个脚本确认能拿到正常响应第一步就算完成了。这里有一个小建议timeout10一定要加。泄漏检测接口背后是大型样本库检索有些慢查询可能拖到十几秒但不设置超时时间的话你的脚本可能因为一个异常请求永远挂在那里。2.3 响应结构、状态码与错误码速查正常的响应一般长这样{ status: found, queried_type: email, risk_level: high, first_seen: 2023-01-15, last_seen: 2024-05-20, breaches: [ {name: some-platform-breach, date: 2023-01-15} ] }常见返回码整理成了表格方便对照状态码含义处理建议200查询成功看 body 里的 status 字段正常解析400参数错误type 或 value 格式不对检查请求体字段401API Key 无效或缺失检查密钥配置403无权限或套餐不允许该类型查询联系服务商开通429触发限流或额度耗尽停止请求按退避策略重试500服务端异常稍后重试记录日志有一个非常容易踩的坑返回 200 不代表“没泄露”。判断是否泄漏要看 body 里的业务字段比如status是否为found而不是只看 HTTP 状态码。我见过有同事把 HTTP 200 直接当成“没有泄露”来处理结果报告全错。HTTP 状态码代表请求是否成功执行业务字段才代表查询结果是什么这两个概念不能混。3. 第二步手机号、邮箱、身份证三类查询的完整代码协议跑通之后就可以写真正能用的代码了。这一章给三类数据各自的实现你可以直接拿去改。3.1 邮箱检测第一个完整的查询函数邮箱检测是最基础的场景适合做第一个完整样例。查询函数需要处理四件事输入清洗、鉴权、响应解析、限流异常。我写一个带自定义异常的版本import requests import os API_URL os.getenv(LEAK_CHECK_API_URL, https://api.leak-check.example/v1/check) API_KEY os.getenv(LEAK_CHECK_API_KEY, ) class RateLimitError(Exception): pass def check_email(email: str) - dict: email email.strip().lower() resp requests.post( API_URL, headers{Authorization: fBearer {API_KEY}}, json{type: email, value: email}, timeout10, ) if resp.status_code 429: raise RateLimitError(触发限流请稍后重试) resp.raise_for_status() data resp.json() return { query: email, found: data.get(status) found, risk_level: data.get(risk_level, unknown), first_seen: data.get(first_seen), last_seen: data.get(last_seen), breaches: data.get(breaches, []), }使用的时候直接调用result check_email(userexample.com) if result[found]: print(f该邮箱已出现在 {len(result[breaches])} 个泄漏事件中风险等级{result[risk_level]}) else: print(当前样本库中未发现该邮箱的泄漏记录)这里把 API Key 从环境变量里读而不是硬编码在代码里是必须养成的习惯。尤其是这类查询涉及极其敏感的个人信息一旦代码和密钥一起被提交到公开仓库别人拿你的密钥刷接口账单会直接爆掉。RateLimitError单独定义而不是直接抛出 HTTP 异常是为了上层做重试策略时能精准识别限流场景。3.2 手机号查询批量质检与脱敏展示手机号场景在实际工作中大多是批量的比如企业要排查一批客户手机号是否在最近某次拖库事件中出现。我写一个从 CSV 读取、逐条查询、脱敏输出的版本import csv import time import requests import os API_URL os.getenv(LEAK_CHECK_API_URL, https://api.leak-check.example/v1/check) API_KEY os.getenv(LEAK_CHECK_API_KEY, ) def mask_phone(phone: str) - str: return phone[:3] **** phone[-4:] def check_phone(phone: str) - dict: phone phone.strip().replace(86, ).replace(-, ).replace( , ) resp requests.post( API_URL, headers{Authorization: fBearer {API_KEY}}, json{type: phone, value: phone}, timeout10, ) resp.raise_for_status() return resp.json() def batch_check_phones(csv_path: str, delay: float 1.0): with open(csv_path, newline, encodingutf-8) as f: reader csv.DictReader(f) for row in reader: phone row[phone] try: data check_phone(phone) found data.get(status) found print(f{mask_phone(phone)} - {泄露 if found else 未发现} - 风险等级 {data.get(risk_level, unknown)}) except Exception as e: print(f{mask_phone(phone)} - 查询失败: {e}) time.sleep(delay)注意这里做了三件事号码格式清洗、日志脱敏、请求间隔控制。脱敏不是可选项打印完整手机号到日志里本身就是一次新的数据泄露。至于time.sleep(delay)在自己没有搞清楚服务商 QPS 上限之前保守地把间隔设为 1 秒是最稳妥的做法。如果你的数据量在几千条以上建议把打印改成写文件输出 CSV 或 Excel 报告同时保留一份失败列表方便跑完以后单独重试。批量的核心是可观测、可恢复而不是一把梭。3.3 身份证查询与实名核验接口的配合使用身份证查询的代码结构和邮箱类似但身份证号码更敏感我建议在代码层就做严格脱敏并且明确区分“泄漏检测”和“实名核验”两个环节。def check_idcard(idcard: str) - dict: idcard idcard.strip().upper() resp requests.post( API_URL, headers{Authorization: fBearer {API_KEY}}, json{type: idcard, value: idcard}, timeout10, ) resp.raise_for_status() return resp.json() def mask_idcard(idcard: str) - str: return idcard[:6] ******** idcard[-4:]如果是企业内部的风险排查流程完整闭环是这样的leak_result check_idcard(110101199001011234) print(f身份证 {mask_idcard(110101199001011234)} 泄漏状态{leak_result.get(status)}) if leak_result.get(status) found: verify_result verify_real_name(name张三, idcard110101199001011234) print(f实名核验结果{verify_result.get(match)})这里verify_real_name指向另一个实名核验服务不包含在 leak-check API 的职责范围内。身份证检测这块我最想强调的一点就是身份证号一旦泄露只能尽量降低损失没法像改密码一样换掉。所以检测结果如果命中意味着这张证件的风险是长期的建议告知对方重视后续监控而不是查完就完事。4. 第三步结果解析、批量任务与避坑经验代码能跑通之后真正的技术含量在于怎么正确解析结果、怎么批量执行、怎么处理各种异常。这一章把三件事讲透。4.1 判断“是否泄露”的正确姿势置信度与风险分级刚接触这类 API 的人容易把“命中了”和“风险高”划等号。其实不完全是。想象一下你的手机号出现在 2012 年一个早已倒闭的论坛的拖库记录里和它出现在上个月一个支付平台的数据泄露事件里风险等级能一样吗所以我在实际项目里不会只输出“泄露/未泄露”而是把结果转成风险评分。评分逻辑参考这几个因素命中数量命中的泄漏事件越多风险越高。最近出现时间越靠近当前时间风险越高老数据可能已经无效或密码已被更换。关联的数据类型如果命中的样本里同时包含密码哈希、支付信息这类高敏字段分数更高。事件类型支付类、金融类平台的泄露比普通论坛泄露更危险。给一个简单的评分函数from datetime import datetime def risk_score(data: dict) - int: score 0 breaches data.get(breaches, []) score min(len(breaches) * 2, 20) last_seen data.get(last_seen) if last_seen: last_dt datetime.fromisoformat(last_seen) months_since (datetime.now() - last_dt).days / 30 if months_since 6: score 40 elif months_since 24: score 20 else: score 5 risk_level data.get(risk_level, unknown) if risk_level high: score 40 elif risk_level medium: score 20 return min(score, 100)这套评分不是官方标准是按业务需要自定义的。但思路值得借鉴不要直接把 API 结果甩给用户而是把它变成一个可以指导行动的指标。用户看到“风险评分 85”和看到“status: found”感知完全不一样。4.2 批量查询的限流策略与队列设计批量查询最忌讳的就是一股脑把几万个请求同时打出去。服务商的 QPS 上限通常写在文档里就算没写你也能从 429 返回码出现的频率里反推出来。控制速率最简单的办法就是固定延迟循环。如果一批数据量很大最好支持断点续跑——记录已经跑到第几条进程中断之后下次接着跑而不是从头再来import json def batch_check_with_resume(csv_path: str, progress_path: str): start_index 0 try: with open(progress_path) as f: start_index json.load(f).get(last_index, 0) except FileNotFoundError: pass with open(csv_path, newline, encodingutf-8) as f: reader list(csv.DictReader(f)) for i, row in enumerate(reader[start_index:], startstart_index): # 执行查询省略具体实现 ... if i % 100 0: with open(progress_path, w) as pf: json.dump({last_index: i}, pf)遇到 429 的时候别立刻重试先停 5 秒再试一次。如果连续多次 429直接退出让日志告诉你服务商的真实限制在哪里而不是硬着头皮把服务打挂。这是我被教育过多次之后学到的教训。4.3 我在实际项目中踩过的几个坑这部分全是真金白银换来的经验分享出来帮大家少走弯路。第一个坑API Key 硬编码被提交到仓库。我第一次用这类接口时图省事把密钥直接写在脚本里后来不小心提交到了 Git 仓库。当天晚上收到服务商的告警邮件说是检测到异常调用。后来才知道GitHub 上到处是扫描密钥的机器人拿到密钥第一时间就去刷接口。从那以后我所有的密钥都只放环境变量或密钥管理服务仓库里一律用占位符并且开启分支保护避免代码被误推上去。密钥泄露和数据泄露一样都是泄露别在小事上栽跟头。第二个坑把 HTTP 200 当成了“没有泄露”。有个同事写了这样一个判断if resp.status_code 200: print(安全)。看到这个的时候我整个人都不好了。HTTP 200 只代表服务端正常响应了请求不代表查询结果是没有泄露。正确的判断必须看 body 里的业务字段。这种错误在初版脚本里特别常见看到这里的朋友一定要引以为戒。第三个坑身份证号做哈希后比对不上。有一次我想当然地认为服务商支持把身份证哈希后查询会更安全于是在本地算了个 MD5 传过去结果老是不命中。后来看文档才发现服务商的样本库用的是带盐或特定算法的哈希直接用标准 MD5 对不上。身份证这类敏感查询如果文档明确要求传明文并进行加密传输那就老老实实按文档来如果服务商支持你传哈希也要搞清楚它要求的哈希算法。想当然的结果就是白跑一次查询还浪费额度。第四个坑中文姓名乱码。在配合实名核验的场景里我遇到过查询结果里的中文姓名变成乱码的情况。原因是请求或响应里的编码没处理好。解决方法是确保 requests 库使用 UTF-8同时在写 CSV 时指定encodingutf-8-sig避免 Excel 打开文件时把中文搞乱。这个坑很小但排查起来特别浪费时间。5. 隐私红线合规使用leak-check API的几条硬规矩技术能力越强越要清楚边界在哪里。leak-check 这类接口处在个人数据保护的敏感地带使用不当很容易从“安全工具”变成“违规工具”。5.1 数据来源授权只能查谁的、不能查谁的合规使用的前提就一句话你只能查询自己拥有、或者经过明确授权的数据。个人用户查自己的邮箱、手机号、身份证没问题这是自查。企业排查自家客户数据是否泄露前提是获得了客户授权或者至少是处理已脱敏数据属于正常安全运营。但任何人都不应该批量查询陌生人的手机号或身份证更不能拿查询结果去撞库、做社工分析、或者反向拼凑个人画像。把接口用来查别人的隐私数据已经不是“技术能力问题”而是法律风险问题。这类行为一旦被处理可能涉及侵犯公民个人信息罪不是罚款就能解决的。我在团队里带人的时候反复强调这一点工具的合规边界比工具本身的技术参数重要得多。重点合规的底线是“授权”。没有授权再强的检测能力也不能调用。5.2 结果处理与脱敏存储查询结果该怎么存也是一个容易忽略的合规细节。我的建议是存储最小化只保存“是否命中”“风险等级”“最近发现时间”这类非原始字段不保存完整手机号、完整身份证号。如果必须要存原始值那就加密存储并且严格控制访问权限。日志同理查询日志里的号码和邮箱一律脱敏不然日志系统被拖走的时候你的日志本身就是下一个泄露源。数据保留时间要短风险排查类任务处理完就可以删掉原始数据没有长期保留的业务必要性。这些规矩看起来繁琐但真出事的时候它们就是你的救命稻草。做安全的人如果自己都不注意数据保护那就不能怪行业声誉被拉低。5.3 与同类服务选型对比与工具链配合最后简单对比一下主流方案方便你按自己的场景选型服务/方案覆盖数据维度适用场景注意点leak-check API邮箱、手机号、身份证多维度个人自查、企业批量排查关注文档限流和维度支持Have I Been Pwned邮箱为主技术团队自查、接入安全平台数据偏海外国内样本覆盖有限Firefox Monitor邮箱个人用户基于 HIBP 数据功能轻量实名核验类接口姓名身份证手机号身份一致性验证需企业资质不负责泄漏检测leak-check API 的优势在于把多个维度合到了一个接口体系里。但对于面向海外用户的平台还是建议同时接 HIBP 做互补因为每一家的样本库覆盖范围不一样没有哪个单一服务商能保证全量。我自己的经验是leak-check 做国内数据维度的主查HIBP 做海外邮箱维度的补充两个结果合并之后再出风险报告覆盖面会明显好很多。最后分享一个我自己跑这套流程的习惯。接到一个新的泄漏检测需求我从来不会直接上全量数据而是先拿 20 条样本跑一遍核对返回格式、状态码、限流表现确认所有预期都正确之后再放开批量任务。密钥只放环境变量日志强制脱敏结果只保留判断需要的字段。这套三步法做下来帮我处理过个人的账号自查也帮企业做过客户数据的风险排查至今还没有因为接口使用不当出过合规问题。希望这篇实战笔记也能让你少走几个弯路。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。