ARTICLE · 1102444
免数据库的合同系统源码分享
免数据库就等于零风险?
省掉的是数据库
省不掉的是安全
合同管理系统 · JSON 文件存储 · 16 文件轻量部署
bbbb.bid · 开源源码拆解
📦 6 Parts + 写在最后
👉 滑动
PART 01
先说结论
能跑但别照用
PART 02
坑一
账号库裸奔
PART 03
坑二
真实数据泄露
PART 04
坑三
并发与日志
PART 05
部署
五步加三项验收
PART 06
清单
十条自查
PART ///
写在最后
省的是钱补的是纪律
00
PART
先说结论:能跑,但别照用
VERDICT · NOT AS-IS
很多小老板挑系统的第一标准是「免数据库」——不用买 MySQL,不用会 SQL,整个文件夹拷走就是备份。今天拆的这套合同生成管理系统,正是按这个思路做的:PHP 加 JSON 文件存储,全站 16 个文件,不依赖任何数据库。听起来很美,对吧?

功能层面确实完整:登录认证、合同在线生成(模板变量填充)、保存归档、统计报表、用户管理、操作日志(15 天自动清理)、个人改密,一应俱全。还配了甲方单位库、送货地点库和合同模板配置,业务闭环是通的。
更难得的是,它并非草台班子:密码走 bcrypt 哈希存储,登录态用 session 管理,日志还有过期清理机制——设计意识是在线的。
但结论必须放在最前面:这套源码不推荐拿去直接用。它的三个问题,全都藏在「免数据库」这四个字里。省掉的是数据库,省不掉的是安全——本篇按反面教材的标准拆,每个坑都给你补法。
一句话结论
免数据库省下的是运维成本,欠下的是安全债
01
PART
坑一:账号库就挂在网址后面
RISK 01 · JSON EXPOSED
先理解这套系统的存储设计:账号在 users.json,日志在 operation_logs.json,合同模板、甲方单位库、送货地点、菜单,全是同名 JSON 文件。数据与 PHP 代码躺在同一个站点目录里。

问题来了:Nginx 默认不认识哪些文件是「数据」、哪些是「页面」。Web 根目录里的东西,浏览器请求什么它就给什么。于是只要不配置访问控制,直接访问 users.json 这个地址,整套账号文件原样下载——这是 JSON 存储类源码的头号通病。
有人说:密码是 bcrypt 哈希,拿到也反推不出来。话没错,但账不能这么算——
名单公开
用户名列表等于交给了攻击者,撞库、爆破从此有了靶子,剩下的只是时间问题。
商业信息裸奔
甲方单位库、送货地点、日志里的合同内容摘要,全是业务敏感数据,一起挂在同一目录下。
补法一步到位:宝塔站点配置里加一条规则,把所有 json 后缀的请求一律拒绝并返回 404,保存重载 Nginx。然后自己用浏览器访问一遍 users.json 验证——返回 404 才算补上。这一步不做,等于把账号库挂在网上营业。
文件型存储的第一个铁律:数据文件和代码放在一起,就必须替它把「直接访问」这条路堵死。
02
PART
坑二:源码包里带着别人的账号
RISK 02 · REAL DATA LEAKED
第二个坑更扎心,也是这套源码最典型的反面教材价值所在——它的问题不在代码,在数据。

发现一:初始化逻辑里硬编码了一个默认管理员账号,用户名是真实姓名,密码也是个位数复杂度的弱口令。源码随包流通,等于把一套真实可登录的凭据公之于众——任何人拿到源码,在同名部署里都能直接登进后台。
发现二:users.json 里躺着29 个真实姓名的用户账号。这极大概率是某次真实使用后遗留的数据,跟着源码包一起流了出来。这已经不是「不严谨」,而是个人信息泄露——《个人信息保护法》之下,无论打包的人是有意还是无意,责任都甩不掉。出于同样的考虑,本文不列出这些姓名。
正确的打开方式,部署后立刻做两件事:
第一时间用系统自带的改密接口修改默认账号密码,弱口令必须换成强口令;
进入用户管理,删除所有遗留账号,或者直接清空 users.json 只保留自己的管理员——按这套系统的设计,清空后首次访问会自动重新初始化。
给所有下载源码的人提个醒:包里若带着他人姓名、手机号、账号一类的数据,一律不得用于真实用途,最稳妥的处理是部署前直接清掉。带着别人的数据上线,风险全是自己的。
03
PART
坑三:并发覆盖与日志的隐性账
RISK 03 · CONCURRENCY AND LOGS
第三个坑不吓人,但最容易被低估:JSON 文件没有并发保护。两个人同时保存合同,后写的会直接覆盖先写的——没有文件锁,没有合并,数据无声无息地丢了,你甚至不知道丢过。
这类问题在演示环境永远复现不出来,因为它只在「人多起来」之后爆发。单人记账、两三个人的小团队,低频使用,大概率相安无事;一旦变成多部门协同、每天几十上百份合同的高频场景,文件存储的短板就是数据事故本身。
日志侧也有讲究。operation_logs.json 记录的是合同内容摘要,属于业务敏感数据,同样要封禁直接访问;好在它有 15 天自动清理,客观上压缩了暴露面——这是这套源码里为数不多值得点赞的设计。
所以适用边界要划清楚:它适合个体户、小门店、低频内部使用;不适合多角色、高频、跨部门的正经业务场景。免数据库方案的能力上限,就写在它的存储方式里。
轻量方案的本质,是把复杂度从「运维」转嫁给「纪律」——纪律跟不上,账迟早要还。
04
PART
正确姿势:五步部署加三项验收
DEPLOY · CHECKLIST
如果看完三个坑,你还是想把它跑起来(毕竟功能对小团队确实够用),按下面的顺序走,把债补在上线之前:
宝塔安装 Nginx 与 PHP 7.4 或 8.0,json、session 扩展默认即有,全程不需要数据库。
整包上传到站点根目录,全目录 755,保证 JSON 文件可写。
最关键的一步:站点配置里拒绝所有 json 后缀请求,重载后用浏览器访问数据文件确认返回 404。
首登立即改默认密码,清空遗留账号;顺手检查源码包里有没有残留的他人数据,有就删。
合同模板、甲方单位库、送货地点,直接编辑对应 JSON 文件或走后台维护,轮播图换成自己的介绍图。
验收也别省,三项走完再交付:生成一份合同、归档、看统计报表出数;确认操作日志正常记录且 15 天清理生效;改密流程走一遍旧密码验证。三样都对,才算「能跑」变成了「敢用」。
老规矩两句:一是源码仅供学习研究,商用前把数据合规与访问控制过一遍;二是拿到任何源码先审后门——这套系统虽然小,但登录、用户管理、文件读写一样不少,鉴权逻辑值得逐个文件过一眼。
05
PART
十条自查清单:JSON 文件型系统通用
CHECKLIST · TEN ITEMS
这一篇的问题不特殊,而是 JSON 文件型源码的共性。不管你手里是哪一套,下面十条逐项过:
浏览器直接访问数据文件,是否一律返回 404;
默认管理员账号是否硬编码在源码里,首登是否立即修改;
源码包里是否残留他人数据——用户表、日志、上传文件逐一翻;
数据文件能否移出 Web 根目录,改由代码内部路径读取;
密码是否哈希存储,全库搜一遍明文比对逻辑;
并发写入有没有文件锁,两人同时保存会不会互相覆盖;
日志里记了什么,保留周期多长,是否需要同步封禁访问;
session 配置是否安全,HttpOnly 与 SameSite 有没有开;
备份机制存不存在,备份文件是否同样加了访问控制;
将来升级覆盖安装,会不会把改过的配置和数据一并冲掉。
十条里前四条是红线,一条不过就别上线。剩下的六条,决定了这套系统在你手里能活多久。
///
LAST
写在最后
CONCLUSION · THOUGHTS
写在最后
免数据库省的是钱,补回来的是纪律
——省下的运维成本,都要以安全债的方式逐笔偿还
这套源码给所有「轻量方案爱好者」提了个醒:部署简单和安全默认,从来是两件事。免数据库把运维成本降到了零,但访问控制、默认凭据、并发保护这些债,一笔都没少,只是从「买服务器」变成了「讲纪律」。
好消息是,这三个坑的补法加起来不到半小时。坏消息是,绝大多数人不会去补——直到 users.json 出现在搜索引擎的收录里。技术选型没有对错,对错在于你有没有为选型交付对应的防线。
如果你手里正好有类似的 JSON 存储系统,今天就把第五部分那十条清单过一遍,比看十篇理论文章都直观。
资源来源:源码库 bbbb.bid关注星标公众号,不定期分享源码干货与安全审计笔记。
既然看到这里了,如果觉得有用,随手点个赞、在看、转发三连吧。
THANKS FOR READING