An open API service indexing awesome lists of open source software.

https://github.com/lzhbhlrpython/card-wallet

A card-info storage platform with TOTP
https://github.com/lzhbhlrpython/card-wallet

Last synced: about 2 months ago
JSON representation

A card-info storage platform with TOTP

Awesome Lists containing this project

README

          

# Card Wallet (Vue + Express + Encrypted SQLite)

一个带本地加密、用户认证与双因素认证 (TOTP) 的信用卡/卡片信息管理示例应用。前端使用 Vue 3 + Vite + Pinia,后端使用 Express + SQLite,并提供基于 WebDAV 的手动远程备份能力。

> 当前版本:1.4.1

## 功能特性
- 用户注册 / 登录(JWT 会话)
- 可选 TOTP 双因素认证(Speakeasy + 二维码)
- **卡片管理**:卡号 / CVV / 有效期基于 AES-256-CBC 加密后存入 SQLite
- **证件管理**:护照、身份证、出入境通行证、驾驶证等证件信息使用 RSA-2048 加密(私钥经 AES 加密存储)
- 支持签发日期和有效期记录(支持长期有效选项)
- 日历组件提供友好的日期选择体验
- 自动识别多种卡组织 (Visa / Mastercard / Amex / UnionPay / Discover / JCB / Diners / Maestro / MIR / CHINA T-UNION / eCNY / 其它)
- 卡片支持记录持卡人姓名(加密存储,仅详情可见)
- 证件支持多语种姓名(本国语言 + 拉丁转写)、多种有效期显示格式
- 服务端校验卡号(含 Luhn 校验,特例:T-Union / eCNY)
- 列表仅展示脱敏信息(卡片末四位、证件掩码号码),详情接口需二次 2FA 验证
- 支持备注 note 字段
- WebDAV 手动备份数据库(时间戳命名)
- FPS 账户管理:列表、详情 (2FA)、创建、编辑、删除、备注隐私保护
- 清空信息(Purge):主密码 + 2FA(如启用)一次性删除卡片与 FPS 账户
- 银行 Logo 多级回退:优先加载 svg,失败尝试同名 png,再回退 fps.png
- 自动登出:token invalid 时自动清除会话并跳转登录页
- **Modal 全局提示组件**:统一的信息提示和确认对话框(替代系统 alert)

## 最近更新(v1.4.0)

v1.4.0 重点优化了证件管理的用户体验,并引入了开发者友好的测试功能:

- **日历组件**:
- 新增统一的 Calendar.vue 日期选择组件,支持日期选择和"长期"选项。
- 支持快速选择年份和月份的下拉选择器,年份范围:当前年份±50年。
- 月份显示使用英文缩写(Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec)。
- 应用于证件管理中的签发日期和有效期输入。
- 支持三种日期格式(YMD/MDY/DMY)的实时切换和显示。

- **证件管理增强**:
- 新增签发日期字段,完整记录证件从签发到到期的完整周期。
- 支持长期有效标识,适用于长期身份证等无明确到期日的证件。
- 证件号码掩码统一为 8 位字符(格式:XX****XX),确保列表显示一致性。
- 证件详情页面优化:采用渐变背景 + 白色浮出层设计,提高可读性。
- 信息展示顺序优化:类型 → 姓名 → 证件号 → 签发日期 → 有效期 → 签发地点 → 备注。

- **Modal 全局提示组件**:
- 封装统一的 Modal.vue 组件和 useModal composable。
- 支持 info/success/warning/error 四种类型,可自定义标题和按钮文本。
- 提供 alert() 和 confirm() 便捷方法,未来将替换所有系统 alert 调用。

- **密码安全增强**:
- 注册、登录、清空数据时,客户端使用 MD5 对密码进行哈希后再传输至后端,避免明文密码在网络传输中暴露。
- 后端存储 bcrypt(MD5(password)),实现双重哈希保护(网络拦截仅得到 MD5,数据库泄露仅得到 bcrypt)。

- **改进的测试脚本**:
- 支持测试签发日期和长期证件(20% 概率生成长期证件)。

- 优化输出格式,更清晰地展示各项测试结果。

- **证件管理**:
- 新增 `documents` 表,支持护照、身份证(ID卡)、出入境通行证、驾驶证等证件类型。
- 证件信息使用 RSA-2048 非对称加密,每个用户拥有独立的 RSA 密钥对。
- 私钥使用 AES-256-CBC 加密后存储在数据库中,公钥用于加密证件数据。
- 列表显示掩码证件号(首尾各2字符,中间星号)、持有人姓名、证件类型。
- 完整证件信息(包括证件号、有效期、签发地点、拉丁转写)需要 2FA 验证。
- 支持多语种姓名:本国语言 + 可选的拉丁字母转写。
- 有效期支持三种显示格式:年/月/日 (YMD)、月/日/年 (MDY)、日/月/年 (DMY)。

- **前端增强**:
- 新增 `/documents` 证件列表页面,支持按类型筛选和排序。
- 新增 `/documents/new` 证件创建页面和 `/documents/:id/edit` 编辑页面。
- 证件详情通过 2FA 弹窗验证后在模态框中显示。
- 导航栏新增"证件"入口。

- **安全改进**:
- 新用户注册时自动生成 RSA 密钥对。
- 旧用户首次登录时自动补充 RSA 密钥对(无缝升级)。
- Token invalid 时自动登出并跳转登录页(已在 v1.2 实现,本次确认)。

## v1.3.0 更新

以下为 v1.3.0 中实现的重要变更,包含数据库迁移、后端验证与前端 UX 改进:

- 后端:新增 `cards.card_type` 字段(English enum),可能值:`credit | debit | prepaid | transit | ecny_wallet_1..4`。
- 通过数据库迁移(PRAGMA table_info -> ALTER TABLE)自动添加列以兼容旧数据库。
- API 在创建/更新时校验并强制网络特殊规则:
- `tunion` (CHINA T-UNION) 强制 `card_type='transit'`,并对有效期/显示做特殊处理。
- `ecny` (eCNY) 必须使用 `ecny_wallet_1..4` 之一;服务端会把 CVV/有效期调整为 000 / 12/99(按规则展示)。
- 列表接口 `/cards` 仍然只返回非敏感元数据(服务器计算 `last4`);卡片详情现在通过列表内弹窗查看(需 2FA),不再提供独立的 `/cards/:id` 路由。

- 前端:显示与交互改进
- 在卡片创建/编辑表单增加“类型”字段(使用统一 `BankSelect` 风格控件),UI 展示为中文标签(信用卡/借记卡/预付卡/公交卡/一类..四类钱包),但提交给服务端为 English enum(`cardType` 字段)。
- `BankSelect` 增加 `readonly` / `allowCreate` / `allowClear` 属性:当 `readonly` 为真时,组件不会基于输入进行过滤,且可通过 `allowCreate=false` 禁止用户创建任意值(用于卡类型选择以避免非法输入)。
- 卡片列表增加“类型”筛选与“按类型”排序,排序使用固定顺序:信用卡 / 借记卡 / 预付卡 / 公交卡 / 一类钱包 / 二类钱包 / 三类钱包 / 四类钱包。
- 卡片项(`CardItem`)将 `类型` 放在左侧,`有效期` 放在右侧并列展示,字体权重与颜色统一以便快速识别。
- 卡片详情通过列表内弹窗查看(需 2FA);独立路由 `/cards/:id` 已移除以避免重复入口点。列表中的“详情”按钮会打开弹窗;删除操作仍使用 2FA 弹窗确认。
- 卡片详情弹窗已升级为更拟真的卡面视觉:基于卡片信息生成确定性渐变配色(近似流体/柏林噪声效果),并在详情中展示持卡人姓名(仅在详情可见)。

- 测试与文档
- `server_test.py` 已更新以在创建测试卡时包含 `cardType` 字段并覆盖特殊网络规则。
- `.github/copilot-instructions.md` 已同步更新,包含后端约束与前端表单/显示规则说明。

数据库兼容性注意:
- 本次发布新增 `cards.card_type` 字段(枚举),服务端在启动时会尝试通过迁移(`PRAGMA table_info` + `ALTER TABLE`)自动添加该列,但建议在升级前先备份 `server/data/database.sqlite` 以防万一。
- 如果你使用旧版本客户端(< v1.3.0),可能无法正确显示或提交 `cardType` 字段;请同时更新前端到 v1.3.0 以确保兼容性。
- 若需回退或审计迁移,请先备份数据库,再参阅 `server/index.js` 中的迁移逻辑与变更记录。

## 目录结构
```
assets/ # 通用静态资源(卡组织 svg 等)
client/ # 前端 (Vue 3 + Vite)
src/
index.html
server/ # 后端 (Express)
index.js
data/ # 运行期生成的 SQLite 数据库 (被 .gitignore 忽略)
```

## 功能概览
- FPS 账户:后端 `fps_accounts` 表与 `/fps` 相关 REST 接口(列表不含 note,详情/修改/删除需 2FA)。
- 前端页面:`/fps` 列表、`/fps/new` 创建、`/fps/:id` 详情、`/fps/:id/edit` 编辑。
- 备注 (note) 仅在 2FA 验证后可见;列表不展示以降低敏感泄漏面。
- 银行 Logo 规则:银行字符串转大写,非字母数字替换为下划线,尝试加载对应 svg;缺失时使用 `fps.png` 兜底。

## 快速开始
### 1. 克隆与安装依赖
```bash
git clone git@github.com:lzhbhlrPython/card-wallet.git card_wallet
cd card_wallet
# 安装前端
cd client && npm install && cd ..
# 安装后端
cd server && npm install && cd ..
```

### 2. 配置环境变量
在根目录或 `server/` 下创建 `.env`(不会提交,已在 .gitignore 中),并提供安全随机值。

可用示例(请勿在生产使用示例值):
```
# server/.env
PORT=3000
JWT_SECRET=change_this_to_long_random_string
ENCRYPTION_KEY=another_long_random_string_for_aes
```
如果你希望前端在构建中访问变量,可使用 Vite 约定:`client/.env` 中以 `VITE_` 前缀命名。

### 3. 启动开发环境
在两个终端分别:
```bash
# 后端
cd server
npm start

# 前端
cd client
npm run dev
```
前端默认在 http://localhost:5173 ,后端在 http://localhost:3000

## 运行流程概览
1. 注册用户:POST /register
2. 登录:POST /login -> 得到 JWT
3. (可选)启用 2FA:
- GET /2fa/setup -> 返回 otpauth_url + QR 二维码 DataURL
- POST /2fa/verify 发送首次验证码确认
4. 管理卡片:
- 列表:GET /cards (无需 2FA)
- 查看详情:GET /cards/:id (需 2FA)
- 新增:POST /cards (无需 2FA)
- 修改:PUT /cards/:id (需 2FA)
- 删除:DELETE /cards/:id (需 2FA)
5. 备份:POST /backup (需 2FA)

所有受保护接口需在 Header 加 `Authorization: Bearer `。
需要 2FA 的接口再提供:
- `x-totp: <6位码>` 或在 JSON body / query 中 `totpCode`。

## 安全注意事项
- 不要把生产数据库 (`server/data/database.sqlite`) 或备份文件提交到仓库,已经通过 `.gitignore` 屏蔽。
- 一定使用强随机的 `JWT_SECRET` 与 `ENCRYPTION_KEY`,并存放在环境变量或秘密管理服务中。
- 当前代码用于示例,未实现:密码复杂度策略、速率限制、账户锁定、审计日志、多租户隔离、密钥轮换等。生产需补充。
- WebDAV 备份为明文 SQLite;如需更强安全性,可:
1. 再次对整个文件进行对称加密后上传
2. 或仅导出加密后的数据片段
- 浏览器端切勿缓存完整卡号;此示例中只有在详情查看时返回完整信息。

## 卡号识别及特殊规则
- CHINA T-UNION: 31 开头 19 位,固定显示银行 CHINA T-UNION,有效期强制 12/99
- eCNY: 0 开头 16 位,CVV 固定 000,有效期 12/99
- 其它受支持组织:使用 Luhn + 长度校验
- 未识别模式:允许 1-80 位纯数字(更自由的自定义/虚拟卡)

## 二因素认证重置流程
重置 TOTP 时,客户端只需验证账号密码:
1. 调用 `POST /2fa/reset/init { password }`(需登录并在 Authorization header 中携带 JWT),服务端验证账号密码后生成新的 TOTP 秘钥并立即绑定(`totp_secret`),返回 `{ otpauth_url, qrCode }` 供用户导入到身份验证器。
2. 用户使用新身份验证器生成的验证码登录即可(无需旧验证码)。

## 备份接口使用示例
```bash
curl -X POST http://localhost:3000/backup \
-H "Authorization: Bearer " \
-H "x-totp: " \
-H 'Content-Type: application/json' \
-d '{"url":"https://your-webdav.example/remote.php/dav/files/user/","username":"user","password":"pass","subdir":"card_backups"}'
```
返回示例:
```json
{"message":"Backup completed successfully","path":"card_backups/cardmanager_backup_20250101_101530.sqlite"}
```

## 构建生产前端
```bash
cd client
npm run build
# 生成文件位于 client/dist/
```
将 `client/dist` 部署到任意静态资源服务器(Nginx、CDN、静态托管等)。

## 自动化批量测试 (server_test.py)
脚本 `server_test.py` 可在根目录批量生成多组织测试卡并调用 `/cards` 创建接口,验证服务端是否正常。

安装依赖(可选,若无 requests 将回退到 urllib):
```bash
pip install requests
```

使用示例:
```bash
# 导出登录后获得的 JWT
export TOKEN="<你的JWT>"
# 全量测试所有支持的卡组织
python server_test.py --base-url http://localhost:3000
# 仅测试 visa / mastercard / unionpay
python server_test.py --only visa,mastercard,unionpay
# 跳过 amex 与 maestro,并输出详细响应
python server_test.py --skip amex,maestro -v
# 列出支持的网络
python server_test.py --list
# 仅查看将发送的数据(不真正请求)
python server_test.py --dry-run --only mir,jcb
# 多轮创建测试
python server_test.py --only visa,mastercard --rounds 5 -v
# 同时测试 FPS 账户(每轮为所有银行各创建一个账户)
python server_test.py --fps -v
# 指定自定义 FPS 银行子集
python server_test.py --fps --fps-banks "HSBC,BOC,ICBC"
```
支持的网络:visa, mastercard, unionpay, mir, amex, ecny, tunion, jcb, discover, diners, maestro

新增 FPS 参数:
- --fps 启用 FPS 账户测试(创建数量 = 轮数 * 银行数)
- --fps-banks 指定逗号分隔银行(缺省则调用 /fps/banks,失败时用内置列表)

注意:
- eCNY / T-UNION 有效期与 CVV 会被服务端调整为 12/99 与 000(eCNY 固定 000,T-UNION 不展示有效期)。
- Purge 功能(清空信息)会同时删除卡片与 FPS 账户。
- 其它卡组织使用 Luhn 合法随机号;不要用于真实支付测试。
- 创建后脚本会再次调用 GET /cards 输出最新条目。

参数说明:
- --token/-t 或环境变量 TOKEN 指定 JWT
- --base-url/-u 指定服务端地址(默认 http://localhost:3000)
- --only 仅测试逗号分隔列出的网络
- --skip 跳过指定网络
- --dry-run 只打印将发送的 payload
- --verbose/-v 打印详细响应
- --list 仅列出支持网络
- --rounds N 重复执行 N 轮(每轮每种网络 1 张)

UI & 测试更新:
- 清空所有卡片使用自定义模态(非浏览器 prompt),输入主密码与 2FA 验证码。
- Mastercard 2-series 检测与生成修复为官方区间 222100–272099。

## 常见问题 (FAQ)
Q: 数据库文件在哪?
A: `server/data/database.sqlite`(首次运行后生成)。

Q: 如何重置管理员密码?
A: 当前没有区分角色。可停止服务,删除数据库文件重新注册,或直接用 sqlite3 CLI 修改 `users` 表。

Q: 支持多用户隔离吗?
A: 是。`cards` 表 `user_id` 外键绑定,查询均按用户过滤。

## 许可证
[GPL-3.0](LICENSE)

## 共创与 AI 协作
详见 [AI_CO_CREATION.md](AI_CO_CREATION.md)