第五章:别再被扒源码了:基于棋牌源代码的前端保护实战

有一天,我们上线测试环境的 H5 版本,刚搭好不到 2 小时,就有人在群里发出完整页面截图、按钮事件名,甚至调试台打印的 Socket 参数。

你会说:“他们是不是拿到源码了?”

不,他们只是按了个 F12,打开了 Chrome DevTools,就把我们整个页面的结构看了个一清二楚。

这其实不是谁的错。Web 前端天然就是“公开”的,任何浏览器都能看到它。但我们能做的,是增加一点点难度,让调试、扒站、逆向变得麻烦,哪怕只是延缓。

F12 能不能防?可以试试让他点不出来

这是很多人最先想到的问题——怎么防止用户打开 F12?

答案是:防不住,但可以恶心人。

我们曾经加过一个极简单的阻止调试的 JS:

document.onkeydown = function (e) {
    if (e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I')) {
        return false;
    }
};

再进阶一点,可以用检测窗口尺寸的方式:

setInterval(function () {
    if (window.outerHeight - window.innerHeight > 100) {
        document.body.innerHTML = '

请勿调试页面

'; } }, 1000);

真正有经验的人会关掉 JS 执行,或者直接用抓包工具,所以我们后来就不靠这招了,而是从结构设计上做隐藏 + 加密 + 延迟加载

核心逻辑不要写在 index.html 里

很多项目偷懒,把核心逻辑、通信地址、用户 token 甚至 socket 实例都写在 index.html 里,打开浏览器的 Sources 面板就能看到全部。

这等于“自爆”。

我们后来一律把 index 页面写成这样:



然后把真正的逻辑都封在加密过的 JS 文件里,配合 JS 混淆器压缩到几乎不可读。

一个典型的混淆前后对比如下:

原始代码

function connectServer(url) {
    socket = io.connect(url);
    socket.on('connect', () => {
        console.log('连接成功');
    });
}

混淆后代码(使用 javascript-obfuscator)

var _0x24a2=["\x63\x6F\x6E\x6E\x65\x63\x74","\x63\x6F\x6E\x6E\x65\x63\x74\x65\x64"];
function _0x57af(_0x1e9d){
 var _0x3e23=io[_0x24a2[0]](_0x1e9d);_0x3e23[_0x24a2[1]](function(){
 console["log"]("连接成功")})
}

重点:不是让别人看不懂,而是让别人懒得看下去


模拟页面“不可见”,核心内容动态加载

在实际部署时,我们常常把 HTML 主体隐藏起来,只在 JS 成功加载后再显示页面。这样做的好处是:

  • 防止用户直接查看静态结构;

  • 核心按钮、参数等都从 JS 控制生成;

  • 结合本地缓存 + 加载动画提升体验。

实现方式很简单:


  
  

我们也可以加一段初始化逻辑判断 cookie 或缓存,避免盗链或直接访问。

前端通信参数加签验签

这是前后端通信的“老套路”,尤其是在服务端 Socket 无法识别用户的情况下,签名机制可以防止伪造请求。

比如发出一个请求时,把时间戳、用户 ID、固定密钥生成一个签名:

function getSign(uid, timestamp) {
    return md5(uid + 'SALT123' + timestamp);
}

然后请求附带:

{
    uid: 1001,
    ts: 1710000000,
    sign: 'a3fbb1ce...'
}

服务端校验:

if (sign !== md5(uid + SALT + ts)) {
    reject('签名错误');
}

是不是绝对安全?当然不是。但这招可以防止最基本的抓包伪造。

页面结构分离:多页面、动态渲染、延迟路由

如果你的组件有多个页面,比如首页、设置页、房间页,建议不要做成静态多页,而是用动态渲染 + 路由加载。

我们实际项目中采用的方式是:

  • 所有页面都引用一个基础模板;

  • JS 控制加载结构;

  • 页面内容通过模板字符串插入 DOM;

  • 页面跳转不刷新,而是用 hash 监听切换。

为什么这么做?很简单:页面结构不落地,就不容易被直接扒。

再配合 HTML 压缩混淆工具(比如 html-minifier),基本上 Sources 面板里能看到的就是一坨不读也罢的代码。

JS 混淆推荐工具

实际用过的几款推荐如下:

  1. javascript-obfuscator
    Node 版本混淆神器,配合 Webpack 插件使用效果更佳。

  2. UglifyJS
    老牌压缩工具,适合 ES5 项目,混淆能力一般。

  3. obfuscator.io
    在线混淆工具,适合快速测试。

我们一般用 javascript-obfuscator 配合打包:

javascript-obfuscator ./src --output ./dist

设置参数推荐:

{
  "compact": true,
  "controlFlowFlattening": true,
  "deadCodeInjection": true,
  "stringArray": true
}
 
  

前端保护不是为了防盗,而是为自己争取时间

写到这里,我必须说一句实话:

前端永远无法做到“安全”。

只要代码在浏览器里跑,就能被看见。我们做的这些混淆、隐藏、延迟加载,本质上不是“加密”,而是“拖延”。

——拖延别人逆向的时间,为你的服务端争取防护时间;
——拖延非专业者的破解兴趣,为项目测试提供正常窗口。

如果你做的是多人互动的项目,或者在维护一套源代码,前端的保护就是你最基本的一层“脸皮”——扒得动不要紧,但别扒得太容易。


下一章,我们将对几个典型组件进行功能设计解读:从“转盘抽奖”、“连线触发”到“古风角色玩法”的组件实现逻辑、资源调用结构、状态管理系统,一步步拆解背后的技术实现。

原文出处以及相关教程请点击

你可能感兴趣的:(前端,javascript,开发语言)