Vercel部署站点的mTLS实现及客户端预登录身份认证方案咨询
嘿,我来帮你梳理下这个问题的解决方案,刚好之前折腾过类似的场景,踩了不少坑😉
一、用Cloudflare给Vercel站点加mTLS的可行方案
首先明确:Cloudflare是完全可以给Vercel部署的站点加mTLS层的,你遇到的header没转发到Origin的问题,大概率是配置环节没做全,我给你捋一遍关键步骤:
Cloudflare端开启客户端mTLS认证
进入你的域名Cloudflare控制台 → 「SSL/TLS」→ 「Client Certificates」,这里你可以选择生成新的客户端证书(给你的用户/设备分发),或者上传已有的证书。然后在「Access」→ 「Access Policies」里创建一个规则,指定需要mTLS认证的路径(比如整个站点/*),把认证方式设为「Certificate」,这样只有携带有效客户端证书的请求才能通过Cloudflare。配置Cloudflare转发mTLS相关Header到Vercel
Cloudflare默认不会把客户端证书的相关信息(比如证书主题、颁发者)转发给Origin,你需要手动添加请求头转换规则:- 进入「Rules」→ 「Transform Rules」→ 「HTTP Request Header Modification」,创建一个新的规则,匹配所有请求(或你需要的路径)
- 添加「Set」操作,自定义Header(比如
X-Client-Cert-Subject),值选择Cloudflare提供的变量cf.tls_client_auth.cert_subject_dn(还有其他变量比如证书指纹、颁发者等,按需选择)
Vercel端允许接收自定义Header
Vercel默认会过滤一些非标准Header,所以你需要在项目根目录的vercel.json里配置,让Vercel接收这些自定义Header:{ "headers": [ { "source": "/(.*)", "headers": [ { "key": "X-Client-Cert-Subject", "value": "$http_x_client_cert_subject" } ] } ] }部署这个配置后,你就可以在Vercel的API路由或页面函数里通过
req.headers['x-client-cert-subject']拿到客户端证书的信息了。排查Header不转发的常见问题
- 检查Cloudflare的SSL模式是不是设为「Full (strict)」,mTLS需要严格的SSL验证
- 用Cloudflare的「Test Rule」功能测试你的请求头转换规则,确认Header是否被正确添加
- 在Vercel函数里打印
req.headers,看看有没有收到自定义Header,如果没收到,可能是规则的路径匹配不对,或者Vercel的配置没生效
二、如果不用Cloudflare,客户端预登录身份认证的替代方案
要是Cloudflare的方案因为某些原因走不通,还有这些方式可以实现客户端/设备的预登录认证:
- 设备指纹绑定:收集客户端的唯一标识(比如浏览器的Canvas指纹、系统信息、UA的哈希值),在用户首次访问时生成一个加密的设备指纹,存在客户端的localStorage或HttpOnly Cookie里,后续访问时服务端验证这个指纹。不过这种方式安全性不如mTLS,适合对安全要求中等的场景。
- 专属API密钥认证:给每个合法设备/客户端分配唯一的API密钥,要求客户端在发起登录请求前先提交这个密钥,服务端验证密钥有效性的同时,可以绑定设备指纹,防止密钥被盗用。密钥建议存在客户端的安全存储里(比如浏览器IndexedDB、移动端Keychain)。
- OAuth2设备授权流:如果是IoT设备、智能终端这类无法直接输入账号密码的设备,可以用OAuth2的设备授权流程:设备展示一个授权码,用户在自己的浏览器上登录并授权该设备,设备拿到访问令牌后即可访问站点,这种方式安全性较高,适合设备类场景。
备注:内容来源于stack exchange,提问作者Ruth T

