如何保障REST API用户注册接口/sign-up的安全性?
解决注册API的手机号验证后被冒用注册的安全方案
针对你遇到的问题,核心是要避免“手机号已验证”这个状态被无关联的请求复用,以下是几个更优的解决方案:
方案1:验证通过后生成一次性绑定手机号的注册令牌
- 在
/verify接口验证验证码通过时,不再只是标记手机号为已验证,而是生成一个短期、一次性、与该手机号强绑定的注册令牌(比如32位随机字符串或带签名的JWT)。 - 将这个令牌返回给前端,同时后端存储令牌的关联信息:手机号、有效期、是否已使用。
- 调用
/sign-up接口时,必须同时提交手机号和该令牌,后端校验逻辑:- 令牌是否存在且未过期
- 令牌绑定的手机号与提交的手机号一致
- 令牌未被使用过
- 校验通过后立即标记令牌为已使用,完成注册流程。
- 优势:令牌有效期可设为5-10分钟(远短于验证码有效期),且一次性使用,就算令牌泄露也无法重复利用,安全性远高于延长验证码有效期的方案。
方案2:绑定验证请求的会话/设备标识
- 在用户发起
/phone-code请求时,后端生成一个唯一会话ID(可通过Cookie返回给前端,或要求前端自行存储),同时将验证码与该会话ID绑定存储。 - 调用
/verify接口时,除了提交手机号和验证码,还需携带该会话ID,后端校验验证码、手机号、会话ID三者是否匹配,匹配通过后标记该会话ID为“已验证手机号”状态,并关联对应的手机号。 - 调用
/sign-up接口时,必须携带同一个会话ID,后端校验:- 会话ID处于“已验证手机号”状态
- 提交的手机号与会话绑定的手机号一致
- 优势:无需额外生成令牌,利用会话上下文实现请求关联,黑客无法冒用已验证手机号,因为没有对应的会话ID。
方案3:将验证状态与用户操作上下文绑定(无令牌/会话简化版)
- 取消“手机号全局已验证”的状态存储,改为在
/verify接口验证通过后,直接向前端返回一个加密的临时凭证(包含手机号、验证时间戳、签名),前端在/sign-up时提交该凭证。 - 后端解析凭证时,验证签名有效性、时间戳是否在有效期内(比如5分钟),同时校验凭证中的手机号与注册提交的手机号一致。
- 优势:无需后端存储额外状态,通过加密凭证实现一次性验证关联,减少存储开销,安全性同样有保障。
方案对比说明
以上方案都不需要延长验证码有效期,而是通过请求关联或一次性凭证的方式,确保只有完成验证操作的合法请求才能发起注册,从根本上避免了手机号验证状态被冒用的风险。
内容的提问来源于stack exchange,提问作者Vsevolod Molchanov
相关产品推荐
相关产品推荐

