首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 ># 用 WorkBuddy 把单机 Flask 回收工具,一夜升级成多用户云版(附安全加固实战) > 标签:#WorkBuddy #Flask #Python

# 用 WorkBuddy 把单机 Flask 回收工具,一夜升级成多用户云版(附安全加固实战) > 标签:#WorkBuddy #Flask #Python

原创
作者头像
用户12616320
发布2026-07-10 22:23:30
发布2026-07-10 22:23:30
580
举报
代码语言:javascript
复制
# 用 WorkBuddy 把单机 Flask 回收工具,一夜升级成多用户云版(附安全加固实战)

> 标签:#WorkBuddy #Flask #Python #实战教程 #AI协作

## 一、背景:单机版用着憋屈

我做二手电脑/配件回收(傲飞回收),之前用 WorkBuddy 写了一个单机版报价工具 `aofei-recycle-app`:Flask + JSON 存定价、xlsx 存客户和库存。功能能跑,但有个致命问题——**只有我自己的电脑能用**,公司其他人想报个价、录个客户,得凑到我屏幕前。

老板一句话定调:"整理一下,新建一个项目,上线部署,一个账套,公司其他人也能用各自账户登录。"

这就是从 **单机版 → 多用户云版** 的升级。下面把完整过程和踩的坑全部摊开。

---

## 二、架构选型(先拍板再动手)

原版是「无用户、文件存储」。要支持多人在线,核心改三件事:**加数据库、加登录、改部署**。

| 维度 | 旧版 v2.1 | 新版 v3.0 |
|------|-----------|-----------|
| 存储 | JSON + xlsx 散文件 | SQLite 单库(WAL 并发) |
| 用户 | 无,谁开谁用 | 多用户登录,管理员/普通用户分权 |
| 数据 | 散落多文件 | 一个 `aofei.db`,一个账套 |
| 新增 | — | 报价历史、用户管理、操作人追踪 |

技术栈:**Flask + SQLite + 自写 session 认证**。(注:最初列了 Flask-Login,后来评审发现它全程没用到,属于死依赖,直接删了,认证用自写装饰器 `@login_required` / `@admin_required` 更轻。)

---

## 三、实现步骤

### 1. 项目结构

```
aofei-recycle-cloud/
├── app.py          # 主程序:所有路由 + 认证 + 权限
├── db.py           # SQLite 连接(WAL + busy_timeout)
├── init_db.py      # 建表 + 从旧版 JSON/xlsx 迁移数据
├── requirements.txt
├── data/           # aofei.db 存放处
├── uploads/        # OCR 配置表上传目录
└── templates/
    ├── login.html
    ├── index.html  # 主界面(9 个功能 tab)
    └── admin.html  # 用户管理页
```

### 2. 数据库设计(核心表)

```sql
-- 用户表(多账户基础)
CREATE TABLE users (
  id INTEGER PRIMARY KEY,
  username TEXT UNIQUE,
  password_hash TEXT,      -- pbkdf2 哈希
  display_name TEXT,
  role TEXT DEFAULT 'user', -- admin / user
  is_active INTEGER DEFAULT 1
);

-- 定价库(110 条配件,7 大类)
CREATE TABLE pricing (
  id INTEGER PRIMARY KEY,
  category TEXT,  -- CPU/GPU/内存/主板/硬盘/...
  name TEXT,
  price REAL,
  UNIQUE(category, name)
);

-- 客户、库存(入/出)、报价历史 ...
```

`init_db.py` 负责把旧版 110 条定价一次性迁过来,客户/库存旧版是空的就跳过。

### 3. 登录认证(自写 session)

```python
def login_required(f):
    @wraps(f)
    def wrap(*a, **k):
        if "uid" not in session:
            return redirect(url_for("login"))
        return f(*a, **k)
    return wrap

@app.route("/login", methods=["POST"])
def login():
    u = query("SELECT * FROM users WHERE username=? AND is_active=1",
              (username,), one=True)
    if u and verify_password(password, u["password_hash"]):
        session["uid"] = u["id"]
        session.permanent = True
        return redirect(url_for("index"))
    return render_template("login.html", error="用户名或密码错误")
```

### 4. 前端迁移:权限门控

普通用户不该看到「新增配件/删除」按钮,用 Jinja2 在服务端直接隐藏入口(后端再兜底校验):

```html
{% if current_user.role == 'admin' %}
  <button onclick="showAddPart()">+ 新增配件</button>
{% endif %}
```

### 5. 本地跑通验证

启动服务后,用 curl 跑通核心链路(这是最关键的一步,光看页面不算数):

```bash
# 登录拿 cookie
curl -c c.txt -X POST localhost:5050/login -d "username=admin&password=aofei123"
# 快速报价:i5-12400F + RTX 3060 + 16G,92 折
curl -b c.txt -X POST localhost:5050/api/quote/quick \
  -H "Content-Type: application/json" \
  -d '{"cpu":"i5-12400F","gpu":"RTX 3060","mem":"16G","discount":0.92}'
# 返回:total=2145, total_with_discount=1973.4  ✅ 匹配准确
```

---

## 四、让 AI 专家团来审代码(WorkBuddy 最香的地方)

功能跑通不等于能上线。我让 WorkBuddy 拉了个**4 人专家团并行评审**(后端 / 前端UX / 部署安全 / 产品测试),每人审不同维度,1 分钟内全部返回。

> 这步强烈推荐:自己写代码容易盲区,让多个 AI 角色从安全、体验、业务角度同时挑刺,比自己复查快 10 倍。

专家团揪出的 **8 个 HIGH 级问题**(不修没法上线):

1. **出库数据迁移 off-by-one**:`range(1,11)` 取索引 0-9 却引用 `row[10]` → 出库记录全丢
2. **OCR 硬编码 Python 路径**:写死开发机路径,换服务器直接挂
3. **存储型 XSS**:转义函数只转了一半,用户输入能注入恶意代码
4. **路径穿越**:文件名用户可控未净化,可读任意文件
5. **SECRET_KEY 硬编码源码**
6. **默认弱口令** admin/aofei123
7. **全站无 CSRF 防护**
8. **定价库普通用户能改价**

---

## 五、安全加固(13 项,全验证通过)

按"不修就没法用"的优先级,把 HIGH 全清,MEDIUM 边用边改:

| 加固项 | 改法 | 验证 |
|--------|------|------|
| CSRF | 自写中间件:`GET /api/csrf` 发 token,写操作校验 `X-CSRF-Token` 头 | 不带 token → 403 |
| 密码哈希 | SHA256 → `werkzeug.pbkdf2`(每用户随机盐),旧账号首次登录自动升级 | hash 前缀变 `pbkdf2:sha256` |
| 定价库权限 | 增/改/删全加 `@admin_required`,前端隐藏入口 | 普通用户改价 → 403 |
| 会话过期 | `PERMANENT_SESSION_LIFETIME = 8h` | — |
| 登录防暴破 | 同账号连错 5 次锁 10 分钟 | — |
| 错误信息 | 4 处不再把 `traceback` 甩给前端 | — |
| 数值校验 | 入库/出库数量>0、金额≥0 | — |
| SQLite | 加 `busy_timeout`,多人并发不锁库 | — |
| 路径穿越 | `secure_filename` + 限 uploads 目录 | `../../etc/passwd` 被净化 |
| XSS | 补全 HTML 转义 | — |
| 死依赖 | 删 Flask-Login | — |
| OCR | 改用 `sys.executable` | 上云不挂 |
| SECRET_KEY | 改环境变量读取 | — |

**关键设计——旧密码平滑升级**:登录时若 `password_hash` 不是 `$pbkdf2$` 前缀,先按旧 SHA256 校验,验证成功后立刻用 bcrypt 覆盖该行。所以默认 admin 第一次登录就自动升级成强哈希,不会卡死你。

---

## 六、成果截图

登录页(多用户入口):

![登录页](shot_01_login.png)

仪表盘(定价库 110 条、客户/库存/报价统计):

![仪表盘](shot_02_dashboard.png)

定价库(管理员可增改,普通用户只读):

![定价库](shot_03_pricing.png)

快速报价(谈单神器,输入配置实时算价):

![快速报价](shot_05_quickquote.png)

用户管理(管理员建账号、分角色、停用):

![用户管理](shot_04_admin.png)

---

## 七、下一步:部署上线

功能验证完,准备部署到腾讯云轻量服务器(推荐方案):

- 单机 **2核4G,约 60-90 元/月**,gunicorn + nginx 反代
- nginx 配免费 SSL(Let's Encrypt)强制 HTTPS
- SQLite 每天定时备份
- 当前低频多人场景完全够用,数据量大了再换 PostgreSQL

上线前补三件:HTTPS、默认口令改强、备份脚本。

---

## 八、总结

从「自己电脑上跑」到「公司所有人用各自账号登录」,核心就三步:**换数据库、加登录、加权限**。但真正让它能放心上线的,是**让 AI 专家团审一遍 + 把安全 HIGH 全清**。

整套过程用 WorkBuddy 一个工具搞定:写代码、跑测试、拉专家评审、改 Bug、截图——全在对话里完成。

**复现方式**:工作区 `aofei-recycle-cloud/` 目录即完整项目, `python init_db.py` 初始化,`python app.py` 启动,浏览器开 `localhost:5050`,默认 `admin / aofei123` 登录后去「用户管理」建同事账号即可。

---

*如果这篇对你有帮,点赞收藏;有疑问评论区见。也欢迎分享你用 WorkBuddy 升级老项目的踩坑。*

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档