【免费下载链接】Portfolio-Website
My Portfolio Website Showcasing the website 3d interactions or experience and my work.
Portfolio-Website 是一个 Three.js 3D 交互作品集网站。它没有把.glb模型文件直接暴露在静态目录中,而是用AES-256-CBC算法将 3D 模型资产加密成.enc密文文件,再由前端通过 Web Crypto API 在浏览器中实时解密、虚拟加载,从根源上防止 3D 模型资产被"右键另存为"式白嫖。本文将完整拆解这套前端加密解密方案。
一、3D 模型资产为什么容易被"白嫖"?🛡️
做 3D 网站的朋友大概率经历过这些糟心事:
- 部署后打开 F12 或右键"图片另存为",就能把你的角色模型下载走;
- 一些资源嗅探工具会直接扫出站点里所有的
.glb、.gltf、.bin文件批量抓走; - 一个精细的角色模型动辄几十上百 MB,制作要数天,被盗用后你几乎无法追责。
核心原因很简单:静态资源目录对全网公开,模型文件等于裸奔。
Portfolio-Website 的做法是:公开目录里只有密文,浏览器永远拿不到原始.glb文件。
二、方案全景:加密资产 + 前端解密 + 虚拟加载 🔐
整套 3D 模型资产保护方案分为三步:
- 构建时用 Node.js 脚本加密:原始模型
character.glb通过 encrypt.cjs 加密为 character.enc; - 运行时浏览器解密:前端 decrypt.ts 调用浏览器原生 Web Crypto 完成 AES-CBC 解密;
- 虚拟 URL 加载:character.ts 把解密出的二进制包装成 Blob 对象 URL,喂给
GLTFLoader+DRACOLoader渲染进场景。
涉及的关键文件如下:
| 文件 | 角色 |
|---|---|
| encrypt.cjs | Node.js 端加密脚本(构建期运行) |
| character.enc | 加密后的 3D 模型资产(部署产物) |
| decrypt.ts | 前端 AES-CBC 解密模块 |
| character.ts | 模型加载入口,衔接 Three.js 渲染 |
| Scene.tsx | 3D 场景组件,触发模型加载与动画 |
💡 注意:本仓库中为了演示保留了原始 character.glb。实际部署时,只应把
.enc密文放入发布目录,原始模型文件留在你自己的制作环境里,这是资产保护的第一道纪律。
三、加密端:encrypt.cjs 如何生成密文 🔑
加密逻辑全部基于 Node.js 内置crypto模块,零第三方依赖,核心在 encrypt.cjs:
- 密钥派生:把口令
Character3D#@做 SHA-256 哈希,得到 32 字节(256 位)的 AES 密钥——口令不需要恰好是 32 字节,哈希保证长度稳定; - 随机 IV:每次加密生成 16 字节随机初始向量(IV),写入密文文件的前 16 字节;
- 密文主体:剩余部分是
.glb全量数据经 AES-256-CBC 加密的产物。
最终character.enc的二进制结构是:
┌─────────────────────┬────────────────────────────────┐ │ 16 字节 IV │ AES-256-CBC 密文主体 │ └─────────────────────┴────────────────────────────────┘为什么 IV 要随机且随文件保存?同样的模型加密两次会得到完全不同的密文,能显著抬高"已知明文"类攻击的成本。这是 3D 模型加密中最容易做错、也最值得做对的细节。
四、解密端:浏览器里的 Web Crypto 🧩
浏览器解密模块是 decrypt.ts,没有引入crypto-js之类的第三方库,而是直接调用浏览器原生的crypto.subtle,流程与加密端严格对称:
- 口令做 SHA-256 哈希,截取前 32 字节,
importKey导入为 AES-CBC 密钥; fetch拉取character.enc,前 16 字节读出 IV,其余是密文(见 decrypt.ts);crypto.subtle.decrypt一次调用完成解密,返回原始模型的ArrayBuffer。
紧接着 character.ts 做了一个很巧妙的处理:
- 把解密出的二进制包成
Blob,再通过URL.createObjectURL生成虚拟 URL; - 虚拟 URL 交给
GLTFLoader加载——Three.js 完全感知不到"解密"这件事的存在。
好处很直接:原始.glb字节流不落磁盘、不进浏览器缓存,只在内存中短暂存在。即使有人抓到了character.enc的响应,拿到的也只是毫无意义的密文。
五、安全边界:这套方案能防谁、防不了谁 ⚖️
诚实地说,前端解密属于obfuscation(混淆)级别的保护,必须认清它的边界:
| 威胁 | 能否抵御 | 说明 |
|---|---|---|
| 右键另存、资源嗅探、随手下载 | ✅ | 拿到的只是.enc密文 |
| 直接爬站搬运 3D 模型资产 | ✅ | 站点中不存在明文模型 |
| 反编译前端 JS 提取口令 | ❌ | 口令在前端代码里,可被提取 |
所以它的正确定位是:抬高"顺手白嫖"的成本,而不是对抗有备而来的逆向攻击。如果你的模型资产商业价值很高,建议在这层之上叠加:
- 服务端解密流式下发(密钥永不出服务器);
- CDN 签名 URL + 访问鉴权;
- 模型内嵌隐形水印用于溯源。
六、三步套用到你自己的项目 🚀
这套 3D 模型资产加密方案可以直接迁移:
- 参考实现:克隆本仓库
git clone https://gitcode.com/gh_mirrors/portfoliow/Portfolio-Website,重点阅读 public/models/ 下的加解密链路; - 加密你的模型:仿照 encrypt.cjs 写一个 Node.js 脚本,换成自己的
.glb和口令,产出.enc文件; - 前端接上解密:复用 decrypt.ts 的 Web Crypto 写法,在模型加载器(GLTFLoader、FBXLoader 等)之前插入解密步骤即可。
写在最后 ✍️
Portfolio-Website 用不到 50 行代码就搭起了一条完整的 3D 模型资产加密解密链路:SHA-256 派生密钥 + 随机 IV + AES-256-CBC 密文落地 + 浏览器 Web Crypto 解密 + Blob 虚拟加载。它防不住专业的逆向者,但足以让所有"右键白嫖党"两手空空——对于大多数 3D 作品集和展示型网站来说,这正是投入产出比最高的保护姿势。
相关模块速查:
- 加密脚本:public/models/encrypt.cjs
- 前端解密:src/components/Character/utils/decrypt.ts
- 模型加载:src/components/Character/utils/character.ts
- 场景入口:src/components/Character/Scene.tsx
【免费下载链接】Portfolio-Website
My Portfolio Website Showcasing the website 3d interactions or experience and my work.
相关推荐
CBC 模式详解:crypto-js 中密码块链接模式的实现与应用
CBC 模式详解:crypto js 中密码块链接模式的实现与应用 你是否在处理敏感数据时遇到过加密不安全的问题?是否想知道如何在前端实现可靠的加密功能?本文将
密码学微信如何加密你的聊天记录?WeChatMsg拆解AES-256-CBC+HMAC-SHA1加密机制
微信如何加密你的聊天记录?WeChatMsg拆解AES 256 CBC+HMAC SHA1加密机制 WeChatMsg(微信聊天记录导出工具) 能提取 Wind
桌面应用数据分析数据可视化终极指南:Authenticator如何保护你的2FA密钥不被泄露
终极指南:Authenticator如何保护你的2FA密钥不被泄露 Authenticator是一款在浏览器中生成两步验证(2FA)代码的工具,为用户提供了便捷
身份认证应用安全前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考