boxmoe_header_banner_img

加载中

yuyu WebSafe v7.0 发布 —— 从能用到真正生产可用


之前发过一篇介绍 yuyu WebSafe 的文章,反响还不错,有不少朋友接入使用。最近这段时间一直在持续迭代,今天发布 v7.0,这个版本我觉得可以说是从「能用的 Demo」正式变成了「生产可用的系统」。

这篇文章主要讲这次更新了什么,以及背后的一些设计考虑。
日后不会 发小版本的更新记录 只有大版本更新才会发文章
小版本更新请看文档站


为什么要重构

坦白说,之前的版本有很多问题是我后来才发现的,有些还挺严重。罗列几个最典型的:

会反复跳转验证页的 Bug

这个问题困扰了我很久。用户明明已经验证通过了,刷新页面又跳回验证页,循环往复。排查下来发现原因不止一个:

一是 Token 生成时就把 JTI 写入了已用列表,导致第一次去服务端验签就返回「已使用」,Cookie 被判定无效,又触发跳转。

二是之前版本做了 IP 绑定,用户在 WiFi 和 4G 之间切换(或者运营商动态 IP)就会 ip_mismatch,Token 失效,又跳转。

三是图片代理请求(4张角色图片并发加载)没有及时释放 Session 文件锁,导致验证请求被阻塞超时。

这些问题单独看都不严重,但加在一起就是「用户体验极差」。

sessionStorage 的选择失误

某个版本我把验证状态的存储从 Cookie 改成了 sessionStorage,本意是想让每次打开新标签页都重新验证(持续保护)。但实际效果是:关闭标签页重开就要重验、多个标签页之间状态不共享、手机 App 内置浏览器每次都要验证……完全不可用。这个版本改回 Cookie 了。

缺少生产环境必要的工具

之前只有核心的验证逻辑,没有:

  • 服务健康检查(不知道 GD 扩展有没有、data/ 目录能不能写)
  • 验证统计(不知道每天有多少人验证、通过率多少)
  • IP 封禁(遇到高频刷请求没办法处理)
  • 紧急关闭开关(系统出问题时只能改代码)

v7.0 主要更新

新增文件

这次加了不少新文件,每个都有具体用途:
算数验证改成图片 换了新题目
config.php — 所有配置集中在这一个文件,部署时只需要改这里,不用翻其他文件找配置项。SECRET_KEY、管理密码、白名单域名、角色库都在这里。

token.php — 比 safe.php 更轻量的 PHP 接入库。safe.php 功能比较全,token.php 专注做一件事:验证 Token。一行代码守卫页面:

require 'token.php';
yuyu_require();

也可以直接当 API 用:GET token.php?token=xxx 返回 {"valid":true}

logout.php — 主动注销验证状态。之前没有这个,用户没有办法「退出」。现在支持三种调用方式:跳转链接、PHP 函数调用、AJAX 请求,可选同时吊销服务端 JTI(防 Token 被他人重用)。

bypass.php — 紧急放行开关。验证系统出问题时,不需要改代码、不需要删文件,访问这个页面输入管理密码就能快速关闭验证放行所有用户,设置有时效(最长1小时自动关闭)。safe.phptoken.php 里都加了对这个开关的检测。

health.php — 服务健康检查。列出所有依赖项的状态:PHP 版本、GD 扩展、data/ 目录权限、Session 功能、Token 生成/验证……支持 JSON 格式,可以接入监控系统。还会自动创建 data/.htaccess 防止数据文件被直接访问。

stats.php — 详细统计和管理。每日/累计验证次数、通过率、IP 黑名单(手动封禁/解封)、高频请求预警、访问日志查看、JTI 紧急清空。用每日 token 鉴权,不需要单独的密码。

Bug 修复

这次修了很多问题,挑几个重要的说:

反复跳转问题:根本解决了。Token 生成时不再预写 JTI,只在真正消耗(consume=1)时才写;Cookie 复用时只做本地格式和过期检查,不调服务端、不消耗 JTI;移除 IP 绑定,网络切换不影响验证状态。

图片加载问题img 请求现在会在读完 Session 后立即 session_write_close(),4张图片并发加载不再阻塞其他请求。

sessionStorage → Cookie:改回 Cookie,24小时有效,多标签页共享,关闭重开不需要重验。

验证页体验:加了骨架屏(图片格子有固定高度,加载时不抖动)、图片失败占位符、加载失败重试按钮、锁定倒计时(不再只显示「X分钟后重试」)、fetch 超时控制(网络慢时不会一直转圈)。

yuyu.php 的一堆问题:Let’s Encrypt 证书续签路径(.well-known)被拦截、bypass/health/logout 没有被排除、URL 里的 token 参数没有重定向清除(会暴露在服务器日志里)、WordPress 多站点冲突等,都在这版修了。

安全加固

  • 管理员密码改为 bcrypt hash 存储,不再明文
  • 管理员登录后执行 session_regenerate_id(true),防 Session Fixation 攻击
  • data/ 目录自动创建 .htaccess,禁止直接访问数据文件
  • HMAC 签名验证使用常数时间比较,防时序攻击(一直都有,这次确认保留)

现在的文件结构

yuyu-v7/
├── config.php          ← 只改这里
├── api.php             ← 后端核心
├── index.html          ← 验证页面
├── safe.php            ← PHP 接入(完整版)
├── token.php           ← PHP 接入(极简版)
├── yuyu.php            ← 零配置全站防护
├── logout.php          ← 注销验证
├── bypass.php          ← 紧急放行
├── health.php          ← 健康检查
├── stats.php           ← 统计管理
├── verify-client.js    ← JS 接入(4种模式)
├── yuyu.js             ← JS 接入(极简版)
├── how-to.html         ← 接入文档
└── README.md
math.php  渲染数学验证
data.php  目录修复
Password.php 生成密码

接入方式没有变化

对于已经接入的朋友,更新只需要替换文件,接入代码不需要改。

静态网站:

<script src="https://ovo.yuyu09.com/verify-client.js"></script>

PHP 网站:

require 'token.php';
yuyu_require();

完整接入文档:ovo.yuyu09.com/how-to.html


后记

这个项目从最初的 demo 写到现在,改了很多遍,踩了很多坑。有些问题是我自己用的时候发现的,有些是朋友反馈的,有些是代码写完之后静下心来仔细看才发现的。

目前觉得 v7.0 是一个相对稳定、可以放心用在生产环境的版本。如果你在使用中遇到任何问题,欢迎在评论里告诉我。

上一次更新已经跑远了✨ 计算中...
(‾◡◝) 本内容里的一些消息,可能已经跟不上时间啦~
感谢您的支持
微信赞赏

微信扫一扫

支付宝赞赏

支付宝扫一扫



评论(0)

查看评论列表

暂无评论


发表评论

北京时间 (Asia/Shanghai)

定位中...
🌤️
--°C
加载中...
体感: --°C
湿度: --%
重要的日子2026年3月20日
重要的日子即将来临。

博客统计

  • 347 点击次数
2026 年 3 月
 12
3456789
10111213141516
17181920212223
2425262728  

已阻挡的垃圾评论

后退
前进
刷新
复制
粘贴
全选
删除
返回首页

💿 音乐控制窗口

🎼 歌词

🪗 歌曲信息

封面

🎚️ 播放控制

🎶 播放进度

00:00 00:00

🔊 音量控制

100%

📋 歌单

0%
目录
顶部
底部
📖 文章导读