项目背景与系统边界
1. 项目核心功能
用户可以:
- 手绘任意图案 (自由轨迹)
- 添加系统内置贴纸
- 输入自定义文字
- 生成最终可下载/打印的贴纸图片
2. 风险类型
-
:用户捕获前端请求后,不断重放试错,以规避规则或自动化尝试生成绘画内容。
-
:用户在客户端层篡改贴纸列表接口,使返回内容被替换为其自定义贴纸 URL,实现未授权内容注入。
-
:在 Windows 虚拟机中,用户通过篡改系统字体,将某个 Unicode 字符替换成自定义矢量图,从而绕过字符白名单、敏感词检测等规则。
-
:用户使用自动化脚本(如 Python + PyAutoGUI)模拟鼠标行为,实现自动绘画、批量攻击或异常高频率操作。
后续的安全设计, 都是围绕上面的风险类型所展开
3.请求重放攻击
工程事实: 只要请求能从客户端发出去, 它就一定能被完整复现. 所以前端做的任何 , 在重放攻击面前都只是
前端能限制的是 , 但是攻击者可能攻击的是 .
- 一次性Token
- 请求签名 + 时间窗
- 一次性Token ->
解决: 请求次数的问题
设计流程
userId、场景类型(DIY贴纸)、创建时间、
即使有 token, 攻击者仍然可能:改参数、改内容、延迟几小时再重放
- 请求签名 + 时间窗(防参数篡改 & 延迟重放)
解决: 请求内容是否被篡改、是否被延迟重放
| 防护 | 解决问题 |
|---|---|
| 防参数篡改 | |
| 防延迟重放 | |
| 防瞬时多次重放 |
前端签名, 后端验签, 并检查: 1. 是否在合理时间窗口内(3-10s内) 2. nonce是否重复使用
4.贴纸接口劫持
问题现象: 、
解决思路: 进行贴纸安全校验, 强制校验贴纸 白名单
- 操作贴纸(插入、编辑、渲染)时,必须对贴纸资源进行 :
- 路径只能来自官方 CDN 域名,如 xxx.cdn.com/...
- 文件名、文件 hash 需与官方贴纸库匹配。
- 不允许用户传入第三方 URL 或本地路径。
- 即便用户劫持接口、篡改返回值,前端添加贴纸的动作仍会被拒绝,从而彻底封堵自定义贴纸注入风险。
在贴纸系统中,我把前端渲染和服务端生成彻底拆开。前端在交互阶段可以使用 URL 渲染,但在最终生成阶段只提交 stickerId 和操作参数
服务端通过 stickerId 映射官方资源并完成合成,从架构上保证即便前端被劫持,最终产物仍然是可信的。
提交给服务端的正确数据结构
❌ 错误方式(永远不要)
✅ 正确方式(你现在的设计)
服务端完整处理流程
- 校验 stickerId 是否官方
- 服务端决定用哪个资源
- 从官方 CDN 加载资源
- 服务端合成最终贴纸
- 生成最终图片 / PDF / 贴纸文件
设计理由
攻击 1: 我前端换成自定义贴纸 -> ❌ 服务端根本不认 URL
攻击 2: 我接口劫持返回第三方 URL -> ❌ 成阶段不会用它
攻击 3: 我篡改提交参数 -> ❌ 服务端拒绝
5.前端字符重建 —— 禁止字体替换伪造字符
。攻击者可能在客户端或虚拟机中替换系统字体文件,把正常字符渲染成任意图形,从而绕过敏感词检测或注入不合规内容。
问题本质
然而
- Unicode 只是字符编号
- 真正显示的是字体文件里的矢量轮廓(glyph)
如何防御
- : 不依赖客户端系统字体,将字符渲染过程完全掌控在前端
- : 将用户输入转换为 Unicode codePoint 数组,例如:
-
: 前端使用项目内置字体文件或矢量库,而非依赖系统字体
-
: 将字符转换为矢量路径绘制,而不是直接用系统 fillText 渲染。
字符 → 矢量路径 → Canvas
