检测移动端短信阅读器预览触发的PIN码提前发送问题
我之前也碰到过这个iOS短信预览搞出来的坑,分享几个实际试过有效的方案给你:
通过请求特征区分真实访问与系统预览
iOS的短信预览请求是系统级爬虫发起的,除了User-Agent为Macintosh,还有几个可识别的特征:- 请求的
Accept头部通常偏向text/plain,不会像真实浏览器那样优先声明text/html - 这类请求不会携带任何Cookie或本地存储的会话标识,是完全独立的无状态请求
- 部分版本的iOS中,预览请求会带有特殊的
X-Requested-With头字段
你可以把这些特征组合起来判断:只有当请求符合真实浏览器的行为(比如正确的Accept头、存在会话标识等)时,才执行PIN码发送逻辑。
- 请求的
改自动触发为用户主动触发
把页面加载时自动发送PIN的逻辑,改成需要用户点击「获取PIN码」按钮才触发。虽然多了一步操作,但能从根源上避免预览触发的问题,同时也更贴合用户意愿——毕竟没人希望还没准备好就收到验证码短信。给验证链接加一次性校验Token
生成短信链接时附带一个唯一的一次性Token参数(比如https://your-domain.com/verify?token=abc123),后端验证这个Token的有效性,并且仅当Token被首次关联到用户会话时才发送PIN码。这样即使系统预览请求过来,因为没有后续的用户会话绑定,也不会触发发送逻辑。UA检测结合多维度验证
既然已经知道iOS预览的UA是Macintosh,可以再补充其他维度的判断:比如真实的Mac Safari浏览器UA会包含Safari标识,而iOS预览的MacintoshUA通常不带;或者检查请求中的屏幕尺寸参数,系统预览的屏幕尺寸和真实手机访问的尺寸会有差异(需要多测试几个iOS版本确认)。
另外还有个小技巧:如果检测到是系统预览请求,直接返回一个不含任何触发逻辑的极简静态页面,只有真实用户访问时才加载完整的验证界面。
内容的提问来源于stack exchange,提问作者Havihavi

