返回探索
指南VibeFix 编辑部更新于 2026年10月31日

不用记密码也能登录:vibe 项目的 Magic Link 与邮箱验证码实战

Magic Link 是一人团队性价比最高的无密码方案,但登录安全从此取决于邮箱安全与邮件送达。本指南讲链接安全七条、送达实测、跨设备处理与兜底方案。

一名男子一边喝咖啡一边低头看手机,正在查看邮箱里的登录邮件
一名男子一边喝咖啡一边低头看手机,正在查看邮箱里的登录邮件

__MEDIA_1__

先说结论:对一人团队的小产品来说,Magic Link(邮箱登录链接)是性价比最高的无密码方案。它比密码登录少了“忘记密码、弱密码、撞库”一整串麻烦,又比 Passkey 和短信验证码便宜得多、接入门槛低得多。但它有个硬伤必须先认清:你的登录安全性,从此取决于用户邮箱的安全性,以及你的邮件能不能准时送达。这篇讲的就是怎么把这两件事做扎实。

文中示例产品“青禾清单”与创始人“沈青”均为虚构,仅用于讲清流程,不对应真实产品。

先划界:这篇不讲什么

站内已经有几篇相邻的指南,各自分工不同:Passkey 那篇讲的是设备生物识别登录,适合“这台设备就是我”的场景;短信验证码那篇讲的是手机号登录,成本按条算、且要处理接码平台;登录与权限那篇讲的是账号体系与角色权限的整体设计。本篇只讲一件事:用邮箱完成“证明你是你”,包括 Magic Link 和邮箱验证码两种形态,以及它们共用的送达、安全与兜底问题。如果你已经定了密码登录、只是想加个“忘记密码”功能,那不是本篇的场景,去看登录与权限那篇里的密码重置一节。

两种形态,先选一个主形态

Magic Link 和邮箱验证码本质上是同一个凭证的两种载体:一个是点一下就能登录的链接,一个是手动输入的 6 位数字。别两个都做、让用户自己选,那只会多一倍的测试量和客服问题。选型只看一个问题:用户主要在什么设备上登录?

如果用户大多在手机 App 里、或者经常在电脑和手机之间切换,优先选 Magic Link。点一下就进,不用在两个设备之间抄数字。但要注意一个经典坑:用户在电脑上点“发送链接”,却在手机邮箱里打开链接——这时链接会在手机浏览器里登录,而不是电脑上。处理办法在后面“跨设备”一节。

如果用户主要在同一台设备上操作、或者你的用户群体里有不少人用“只能收邮件、不能点外链”的企业邮箱(有些企业邮箱会把链接改写成安全跳转,导致链接提前失效),优先选 6 位验证码。数字可以口头转述、可以抄,兼容性最好。缺点是用户要多一步输入,而且你要自己做防暴力破解。

青禾清单(虚构)最初两个都上了,结果客服一半的问题是“我点了链接又输了验证码,到底哪个算数”。后来只留 Magic Link 为主、验证码为备用:链接打不开时,页面上才出现“改用验证码登录”的入口,主路径永远只有一条。

链接的安全七条,缺一条都别上线

Magic Link 的安全不靠“链接很长所以猜不到”这一条,它靠的是一组互相兜底的规则。下面七条是上线前的硬性检查项,AI 生成代码时最容易漏掉后面几条,逐条对着查:

  • Token 只存哈希,不存明文。数据库里被拖走时,明文 token 等于所有账号的万能钥匙。生成 32 字节随机数,存 SHA-256 哈希,邮件里才放原始值。查库时同样先哈希再比对。
  • 15 分钟过期。别学某些产品给 24 小时。链接在邮箱里躺得越久,被转发、被归档、被别人翻到的概率就越大。15 分钟对正常用户绰绰有余,过期就重新发。
  • 一次有效,用完立即作废。不管登录成功还是失败后重试,同一个 token 第二次使用必须拒绝。否则用户把邮件转发给同事“帮我看一眼”,对方也能登录。
  • 新链接发出,旧链接全部作废。用户连点三次“重新发送”,邮箱里就躺着三条链接,只有最后一条能用。否则用户随手点开第一条旧链接登录失败,还以为是你的 bug。
  • 不透露账号是否存在。输入一个没注册过的邮箱,页面也要显示“如果该邮箱已注册,登录链接已发送”,耗时和文案与已注册时完全一致。否则攻击者可以拿你的登录框当“用户枚举器”,一个个邮箱试出谁是你的用户。
  • 链接只能走 HTTPS,且域名是你自己的。别用邮件服务商默认的跳转域名当登录域名,用户看到陌生域名会犹豫,钓鱼者也正好可以仿冒。链接域名必须和你的产品主域名一致。
  • 登录成功后立即发通知。“你的账号刚在新设备登录”这封邮件或站内通知,是最后一道防线。用户本人没登录却收到通知,还能立刻改邮箱密码、联系你冻结账号。

验证码形态的安全规则大同小异,但要多两条:6 位数字只有一百万种组合,必须限制尝试次数(例如 5 次错误就锁定该邮箱 15 分钟),并且同一邮箱 1 分钟内只能发一次、1 小时内最多发 5 次。否则攻击者可以写个脚本慢慢猜,或者用你的发信接口给别人刷垃圾邮件。

邮件送达:登录链接首先是一封能送到的邮件

很多 Magic Link 上线第一天翻车,不是因为代码错了,而是邮件进了垃圾箱、或者干脆被拒收。登录邮件的送达问题要当成登录功能的一部分来测,而不是“等用户反馈再说”。

第一步是把发件身份做对:发件域名用你自己的产品域名(比如 login 专用子域名),配好 SPF、DKIM、DMARC 三条 DNS 记录。这三条的作用是告诉收件方“这封邮件确实是我发的、没被篡改”。AI 生成代码时经常只接通发信 API 就交差,DNS 这三条没人配,结果就是 Gmail 直接判为可疑。

第二步是测主流邮箱的实际表现。至少用 Gmail、Outlook、QQ 邮箱、163 邮箱各注册一个测试账号,真实走一遍“发链接、收信、点链接”全流程,记下每个邮箱从点击发送到收信的耗时。如果某个邮箱 consistently 超过 1 分钟,你的“15 分钟过期”对它就等于“14 分钟”,文案里要写“链接 15 分钟内有效,若未收到请检查垃圾箱”,而不是只写“已发送”。

第三步是处理“链接被提前点开”的问题。企业邮箱和某些安全网关会在邮件到达时自动“预访问”链接做安全扫描,这会把你的一次性链接提前消耗掉。缓解办法有两个:一是链接落地页先显示“确认登录”按钮,点按钮才真正消耗 token;二是检测到链接已被消耗但会话未建立时,给出明确的“链接已被使用,请重新发送”提示,而不是含糊的“登录失败”。青禾清单(虚构)上线第一周被这个问题坑了三次,改成“点链接先确认、再登录”之后,相关客服工单直接归零。

页面与文案:把等待变成可预期的事

Magic Link 体验的好坏,一半在页面文案上。用户点完“发送链接”之后最焦虑的三个问题是:发到哪个邮箱了?要等多久?没收到怎么办?你的页面必须在用户问出口之前回答完。

“发送成功”页要写清四件事:发往的邮箱地址(打码显示中间部分即可)、链接有效期、检查垃圾箱的提醒、以及“重新发送”按钮和冷却倒计时(60 秒)。不要只写一个孤零零的“邮件已发送”。

跨设备问题要单独处理:如果用户在电脑上请求链接、却在手机上点开,手机上登录成功后,电脑页面不能一直转圈。做法是:电脑页面轮询登录状态(每 3 秒问一次服务器“这个请求登录成功了吗”),一旦手机端完成登录,电脑页面自动进入已登录态;如果用户 5 分钟内没在任何设备完成登录,电脑页面提示“仍未收到?重新发送或改用验证码”。

过期与失效页面也要说人话。不要显示“token_invalid”这种内部错误码。三种情况三种文案:“链接已过期,请重新发送一个新的”“链接已被使用过,每个链接只能用一次”“链接无效,请确认你点的是最新一封邮件”。用户能根据文案自己解决问题,就不会来找客服。

兜底:当邮箱本身不可用时,用户怎么办

再好的 Magic Link 都会遇到用户收不到邮件的时候:邮箱服务商故障、用户换了邮箱、公司邮箱停用。没有兜底方案的登录系统,等于把“找回账号”的权力完全交给了邮箱服务商。

最小可行的兜底是两条:第一,保留一个备用的登录方式,通常是密码或 OAuth(Google/GitHub 登录),让用户在邮箱不可用时还能进得去;第二,客服人工验证流程要有书面标准——用户需要提供什么(注册时间、最近订单、绑定的手机号后四位),客服核实后可以手动更换绑定邮箱,而不是口头答应“帮你改一下”。

反过来也要想清楚:备用方式不能成为后门。如果密码是兜底,那密码本身的安全要求(长度、错误锁定、泄露检测)一点都不能放松,否则攻击者根本不用攻 Magic Link,直接走最弱的备用通道就行。安全链的强度,永远等于最弱的那一环。

上线验收清单

按这张清单逐项打勾,全部通过再上线:Token 存哈希且 15 分钟过期、一次有效、新链接作废旧链接、不透露账号存在性、链接域名与产品域名一致、登录成功有通知、验证码有尝试次数与发送频率限制、Gmail/Outlook/QQ/163 四家实测收信与点击全通、企业邮箱预访问场景有确认页兜底、发送成功页写清邮箱/有效期/重发冷却、过期与已使用文案区分清楚、备用登录方式与客服换绑流程已写成文档。少任何一项,上线后都会以客服工单的形式还回来。

最后一句大实话:Magic Link 不是“去掉密码就安全了”,它是把密码的麻烦转移到了邮箱和邮件系统上。你愿意花半天时间把 DNS、过期策略、失效文案这三件事做对,它就是一人团队最省心的登录方案;你只想让 AI 生成一个发链接接口就上线,那它就是最容易在上线第一天翻车的登录方案。

让 AI 生成代码时,必须写进提示词的六句话

一人团队大多是让 AI 写登录代码,代码本身通常能跑,问题出在提示词里没提要求、AI 就按“最省事”的方式实现了。下面六句话直接抄进你的提示词,生成结果会可靠得多:第一,Token 生成用密码学安全的随机数,数据库只存哈希;第二,Token 有效期 15 分钟、一次有效、新 Token 发出即作废旧 Token;第三,注册与未注册邮箱返回完全相同的提示文案与响应耗时;第四,登录链接域名必须与产品主域名一致、走 HTTPS;第五,登录成功后发送新设备通知;第六,所有失败场景(过期、已使用、无效)返回不同的业务错误码,前端据此显示不同的中文文案,禁止直接把错误码透传给用户。

拿到 AI 生成的代码后,别只看“能不能登录”,按这份审查清单逐项过:Token 表有没有过期时间字段和已使用标记?校验逻辑是不是“先查哈希、再查过期、再查已使用、最后标记已使用”这个顺序?顺序错了就会出现“过期链接被标记已使用、用户重新发链接又被判定重复”之类的怪问题。重发接口有没有频率限制?登录成功后 Session 是不是重新生成、旧 Session 是否失效?邮件模板里的链接是不是完整 URL、而不是相对路径?这五项里任何一项答不上来,都先别合并代码。

上线后第一周,盯住四个数字

上线不等于做完,第一周的四个数字会告诉你哪里还没做对:第一,从点击发送到用户点开链接的中位耗时,正常应该在 1 分钟以内,超过 3 分钟就要查发信通道和收件方延迟;第二,链接过期率,也就是“发出的链接里、最终因过期而失效的比例”,超过 10% 说明你的有效期文案或送达速度有问题,先查垃圾箱率、再考虑把有效期从 15 分钟放宽到 30 分钟,而不是一上来就放宽到几小时;第三,重发率,单个用户一天内重发超过 3 次,往往是“链接被企业网关预访问消耗”或“邮件延迟”在作怪,按前面说的确认页方案处理;第四,客服工单里“收不到邮件”的占比,如果连续三天都有这类工单,别只回复用户“请检查垃圾箱”,去查发信域名的 SPF、DKIM、DMARC 是否真的生效,有没有被某个邮箱服务商整体拒收。

还有一个容易被忽略的指标:登录成功后 24 小时内的“换绑邮箱”请求量。如果这个数字突然上涨,很可能是有人在用泄露的邮箱批量试链接——虽然一次有效的链接本身很难被猜中,但攻击者可以用你的发信接口给大量用户发骚扰邮件。应对办法是给同一邮箱的发送频率再收紧一档,并在发送成功页明确写“如果你没有请求登录,请忽略这封邮件”,让收到骚扰邮件的用户安心,而不是恐慌。

常见问题:上线前一定会被问到的五个

“用户没有邮箱怎么办?”——那就不是 Magic Link 的目标用户。给这类用户留密码或 OAuth 通道,但不要为了极少数用户把主路径改复杂。主路径服务 95% 的人,兜底服务剩下的 5%。

“链接能不能长期有效、方便用户收藏?”——不能。长期有效的登录链接等于一把没有有效期的钥匙,邮箱一旦泄露、旧邮件被翻出来,账号就跟着丢。用户要的是“每次登录都方便”,不是“收藏一个链接永久登录”;前者靠“记住设备 30 天”实现,后者是安全漏洞。

“记住设备怎么做才安全?”——登录成功后给设备发一个长期有效的刷新凭证(存 HttpOnly、Secure、SameSite 的 Cookie),有效期 30 天,设备列表页可查看、可单独吊销。记住的是设备,不是邮箱链接;链接本身依然一次有效。

“验证码和链接能不能共用同一套 Token?”——可以,但不要共用同一个校验入口。链接 Token 是 32 字节随机数、验证码是 6 位数字,两者的尝试次数限制、过期策略、错误文案都不同。共用存储表可以,共用校验逻辑一定会把其中一边的限制带偏。

“测试环境怎么测?”——测试环境单独配发信域名或沙箱发信通道,禁止往真实用户邮箱发测试链接;同时给测试账号准备“测试邮箱收件箱”服务,能直接读到测试邮件内容。最忌讳的是开发图方便、在生产环境给自己的真实邮箱反复发链接测试——那既污染生产数据,又可能触发频率限制、连累真实用户。

阅读 0评论 0

评论 (0)

ME
0/1000
评论加载中...
浏览项目广场发布你的项目

相关文章

桌前边用笔记本电脑边在纸质本子上记笔记的实拍照片,呼应给未来自己留手册的主题
指南
停三个月还能接回来:一人项目的断档复工手册

一人项目最常见的死法不是做不出来,而是放下就拿不起来。本文讲复工手册五件套、怎么写给失忆的自己、AI 协作断档怎么接、复工第一天的固定顺序,附验收清单。

开发工作流独立开发学习与成长