Article
brucedaily工程实现复盘
4 分钟阅读 · 66 次浏览 · 2026-06-24 19:58:52.872919+08:00
这是一篇面向公开阅读的工程复盘,记录 `brucedaily` 个人网站从技术选型到实现落地的主要思路。
brucedaily 工程实现复盘
这是一篇面向公开阅读的工程复盘,记录 brucedaily 个人网站从技术选型到实现落地的主要思路。
项目目标
brucedaily 是一个个人博客与应用展示系统,同时提供登录后可见的留言功能和基础管理后台。
核心目标有三个:
- 内容发布:支持文章、应用项目、详情页和公开列表。
- 私有互动:用户可以给站长留言,留言不进入公开列表。
- 轻量管理:站长可以通过后台维护内容、用户、留言和站点设置。
这个项目没有追求复杂的微服务或前后端分离,而是优先保证小团队和个人维护时的稳定、清晰、可部署。
技术栈
后端使用:
- Python 3.12
- FastAPI
- SQLAlchemy 2.x
- Alembic
- Pydantic
- Jinja2
前端使用:
- Jinja2 服务端模板
- 原生 CSS
- 少量表单交互
生产运行环境采用:
- PostgreSQL
- Nginx
- systemd
- HTTPS
选择这套技术栈的原因很务实:个人站点的主要复杂度在内容、权限和部署闭环,而不是前端状态管理。服务端模板可以减少构建链路,让页面、权限和数据查询保持在同一个工程上下文中。
架构方式
项目采用单体应用结构,按职责拆分模块:
app/
core/ 配置、权限、认证、安全工具
db/ 数据库连接和会话
models/ 数据表模型
schemas/ 请求与响应结构
routers/ 页面和 API 路由
services/ 业务服务
templates/ 页面模板
static/ 静态资源
migrations/ 数据库迁移
tests/ 自动化测试
这种拆分的好处是边界足够清楚,但不会为了抽象而抽象。个人项目最怕把简单问题做成复杂平台,所以这里让每一层只承担必要职责。
核心模块
文章模块
文章模块支持标题、摘要、正文、封面、分类、标签、状态和发布时间。
正文采用 Markdown 编写,后端渲染为 HTML,再进行安全清洗。公开页面只展示已发布内容,草稿和隐藏内容不会出现在公开列表中。
应用展示模块
应用模块用于展示个人项目或工具,包括名称、简介、版本、平台、截图和下载信息。
它和文章模块类似,也有公开状态控制。这样站长可以先在后台整理内容,确认无误后再发布。
留言模块
留言功能面向登录用户开放。用户提交的留言只对本人和管理员可见,不提供公开留言墙或公开评论区。
这个设计主要是为了降低内容审核和隐私泄露风险。个人站点需要互动,但不一定需要公开讨论区。
用户与权限
系统包含普通用户和管理员两类角色。
普通用户可以:
- 注册和登录
- 提交留言
- 查看自己的留言记录
管理员可以:
- 管理文章
- 管理应用
- 处理留言
- 管理用户状态
- 调整站点设置
- 查看审计日志
权限控制放在后端,不依赖前端隐藏按钮来保证安全。
认证实现
认证使用 Cookie 会话思路实现:
- 用户提交登录信息。
- 后端校验密码哈希。
- 生成登录令牌。
- 通过 HttpOnly Cookie 保存登录状态。
- 后续请求由后端解析 Cookie 并加载当前用户。
这样可以减少前端直接接触令牌的机会,也更适合服务端模板页面。
密码不明文保存,而是保存哈希结果。生产环境还需要启用安全 Cookie、关闭调试接口,并使用足够强的密钥。
前端实现
前端没有使用 React 或 Vue,而是使用 Jinja2 模板。
主要页面包括:
- 首页
- 文章列表和详情
- 应用列表和详情
- 登录和注册
- 留言页
- 个人留言记录
- 管理后台页面
样式集中在一个 CSS 文件中维护。这样做有两个现实好处:
- 改文案和布局时定位简单。
- 部署时不需要额外构建前端产物。
对于当前体量的个人网站,这种方案比引入复杂前端工程更容易维护。
Markdown 安全处理
文章和应用介绍支持 Markdown,但 Markdown 渲染后的 HTML 不会直接输出。
处理流程是:
- Markdown 转 HTML。
- 白名单清洗 HTML 标签和属性。
- 输出清洗后的内容。
这样可以保留写作体验,同时降低脚本注入风险。
文件上传
上传功能用于文章封面、应用图标、截图和附件。
实现策略包括:
- 限制文件大小。
- 限制允许的扩展名。
- 上传后重新命名。
- 保存文件校验信息。
- 上传文件作为静态资源提供,不作为代码执行。
上传是个人站点里常见的风险点,因此实现时优先考虑边界清晰和默认保守。
审计日志
后台写操作会记录审计日志,例如内容创建、编辑、删除,留言处理,用户状态变更等。
审计日志不解决所有问题,但它能回答一个很重要的问题:某个后台状态是谁在什么时候改的。
本地复现思路
如果要复现类似系统,可以按这个顺序推进:
- 创建 FastAPI 应用入口和配置系统。
- 建立数据库模型和迁移。
- 实现用户注册、登录和当前用户识别。
- 增加文章和应用的 CRUD。
- 增加公开列表与详情页。
- 增加留言功能和权限边界。
- 增加管理后台页面。
- 增加上传、审计日志和站点设置。
- 编写测试覆盖核心权限和内容可见性。
- 最后再处理生产部署和 HTTPS。
这个顺序的好处是每一步都有可验收结果,不会一开始就陷入完整系统的大而全设计。
测试策略
测试重点放在风险较高的地方:
- 注册和登录流程
- 普通用户与管理员权限差异
- 文章和应用的公开可见性
- 留言只能被本人和管理员查看
- 后台页面访问控制
- Markdown 清洗
- 上传限制
相比追求覆盖率数字,更重要的是覆盖权限边界和公开页面行为。
部署思路
生产部署采用常见的 Linux Web 应用方式:
- 应用由进程管理器托管。
- Nginx 负责反向代理和静态资源。
- PostgreSQL 作为主数据库。
- HTTPS 保护传输。
- 环境变量或配置文件保存生产配置。
- 数据库变更通过迁移工具执行。
公开文档不建议放出完整服务器命令、账号、路径或后台入口。部署细节应保留在内部文档中。
安全取舍
这个项目采用了几条基础安全原则:
- 不提交生产配置。
- 不保存明文密码。
- 登录状态使用 HttpOnly Cookie。
- 后台权限由后端校验。
- 留言不公开展示。
- Markdown 输出前做清洗。
- 上传文件不作为代码执行。
- 生产环境关闭调试能力。
- 关键写操作记录审计日志。
个人网站不等于低风险。只要开放注册、登录、上传或后台,就需要把权限边界当成核心功能来实现。
可扩展方向
后续可以继续扩展:
- 将本地上传切换到对象存储。
- 增加文章归档和 RSS。
- 增加更细的后台操作审计。
- 增加后台通知。
- 增加自动备份和恢复演练。
- 为公开 API 增加限流。
不过在扩展之前,先保持系统简单、稳定、容易恢复,通常比堆功能更重要。