kevin 5b227b71ef feat: 文章 CRUD 接口 JSON 化——/api/admin|my/articles
- article.go:articleForm 加 json tags,新增 parseArticleFormJSON(绑定+
  去白);ArticleCreate/ArticleUpdate/ArticleDelete 增加 redirectPath 参数,
  校验失败改 APIError 400、DB 错误 500,成功 {ok,redirect}(原 renderForm
  分支移除);id 改用 parseUintParam 数值化
- my_articles.go:MyArticleCreate 复用 ArticleCreate(db, /my/articles);
  MyArticleUpdate/MyArticleDelete 保留 author_id 所有权约束(404
  article_not_found);my 更新不触碰标签(表单无该字段,与旧行为一致)
- main.go:admin/my 文章旧 POST 路由移除,改 POST/PUT/DELETE
  /api/admin/articles[/:id] 与 /api/my/articles[/:id]
- 模板:article_create.html/my_article_form.html 表单改 blogAPI 提交
  (easyMDE.value() 同步正文、editor e.submitter 分流草稿/发布),错误内联
  articleError/myArticleError;article_list.html/my_articles.html 删除改
  blogDelete 委托(base.html 新公共函数,DELETE + reload 保筛选状态)
- main_test 冒烟补文章 CRUD 断言;go build/vet/test 全绿
2026-08-27 19:40:02 +08:00
2026-08-27 19:03:03 +08:00
2026-08-27 19:03:03 +08:00

Go Blog

一个简洁、快速的博客引擎,使用 Go + Gin + Tailwind CSS 构建。支持 SQLite 和 MySQL,首次运行自动完成配置。

功能特性

  • 文章管理 — 文章的创建、编辑、删除,支持标签分类、自定义发布时间和更新时间
  • Markdown 渲染 — 文章与评论支持 GFM Markdown(表格、任务列表、删除线),代码块语法高亮 + 一键复制,标题锚点链接,图片懒加载与灯箱预览
  • 评论系统 — 文章评论功能,后台可审核(通过/拒绝/删除),支持评论设置
  • 用户系统 — 用户注册、登录,角色分为管理员(admin)和作者(author
  • 角色权限 — 管理员可访问后台管理面板;作者可管理自己的文章
  • 个人中心 — 上传头像(支持裁剪)、编辑个人信息、修改密码
  • 站点设置 — 自定义站点标题、副标题、favicon 图标
  • 导航管理 — 自定义首页导航链接,支持图标
  • 瀑布流布局 — 首页文章以瀑布流展示,支持无限滚动加载
  • 阅读统计 — 文章阅读量统计,带机器人流量检测
  • 附件上传 — 文章支持上传附件,基于内容寻址自动去重
  • RSS 订阅 — 自动生成 RSS Feed/rss/feed),链接使用站点设置的规范地址
  • 搜索功能 — 文章全文搜索
  • 多语言 — 支持中文 / English,自动检测浏览器语言或手动切换
  • 自适应界面 — Tailwind CSS,桌面端和移动端均可正常使用
  • 安全加固 — 会话密钥加密随机、Cookie HttpOnly/SameSite=Lax/HTTPS Secure、全站 CSRF、SQL 注入防护(参数化+路由 ID 数值化)、/uploads 白名单挂载(SQLite 数据库不可下载)、登录限速(IP+用户名,5 次失败锁 15 分钟)、附件越权校验、上传安全(危险扩展黑名单+magic-bytes 检测+头像 JPEG 重编码)、Gravatar 默认关闭、禁用用户会话实时失效,完整清单见 SECURITY_TODO.md
  • 开箱即用 — 首次运行自动创建配置文件、数据库;管理员账号密码为随机生成并仅一次性打印(不再使用 admin/admin

技术栈

层级 库/工具
路由 gin
ORM gorm
SQLite glebarez/sqlite(纯 Go,无需 CGO
Session gin-contrib/sessions
配置 gopkg.in/yaml.v3
密码 golang.org/x/crypto
文件校验 gabriel-vasile/mimetype
CSS Tailwind CSS(构建期静态生成,见 scripts/build_tailwind.sh

快速开始

go run .

打开 http://localhost:8080 登录。首次运行时会自动创建管理员账号 admin,初始密码为随机生成并仅一次性打印在日志中——请立即记录并登录后修改(SECURITY_TODO #12,不再使用默认 admin/admin)。

前端资源全部本地化(static/css/app.css 为 Tailwind 静态构建产物,已提交)。修改 HTML 模板/Go 代码中的 Tailwind 类后,运行 ./scripts/build_tailwind.sh(需 Node ≥ 18,npx 可用)重新生成并提交新产物;vendor 库更新同理重新下载到 static/vendor/ 并提交。

安全状态一览见下方 安全加固 章节,完整修复清单与验证记录见 SECURITY_TODO.md

配置

首次运行时,配置文件会自动生成:

平台 配置文件路径 数据存储路径
Linux /etc/blog_go/config.yaml /srv/blog_go/
Windows ./win/etc/blog_go/config.yaml ./win/srv/blog_go/
# config.yaml
database:
  type: sqlite        # sqlite(默认)或 mysql
  dsn: ""             # MySQL 连接串,sqlite 模式下忽略
web:
  port: "8080"                # Web 服务端口,"" 或 "0" 可只启用 socket
  socket: ""                  # unix socket 路径(Linux 部署推荐,见 install_linux.sh
  trusted_proxies:            # 可信反向代理 IP/CIDR;直接影响 X-Forwarded-For
    - 127.0.0.1               # 仅列表内的代理可设置客户端 IP(防 XFF 伪造)
    - ::1
path: ./win/srv/blog_go  # 数据存储路径(数据库、上传文件)
secret: <自动生成>     # Session 加密密钥;缺失时拒绝启动

使用 MySQL

编辑 config.yaml

database:
  type: mysql
  dsn: user:password@tcp(127.0.0.1:3306)/blog_go?charset=utf8mb4&parseTime=True&loc=Local
web:
  port: "8080"

先创建数据库:

CREATE DATABASE blog_go CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

项目结构

目录 作用
config/ 配置加载与自动创建(区分 Linux/Windows 路径)
models/ 数据模型:用户、文章、标签、评论、附件、阅读统计、站点设置等 + GORM 初始化
handlers/ HTTP 请求处理:首页、文章、登录/注册、评论、后台管理、个人中心、RSS、上传校验
middleware/ 中间件:登录/角色鉴权、CSRF、HTTPS 检测、安全响应头(CSP/HSTS 等)
i18n/ 中英文翻译与浏览器语言检测
templates/ HTML 模板:layouts 公共布局、pages 前台、admin 后台、user 用户文章
static/ 静态资源:Tailwind 产物、前端 Markdown 渲染器、vendor 本地化第三方库(marked、highlight.js 等)
scripts/ 构建辅助脚本(Tailwind 重建、数据库迁移 SQL

根目录文件:main.go(入口 + 路由注册)、main_test.gohandlers/_test.go(测试)、fresh.conffresh 热重载配置)、install_linux.shLinux 部署脚本)。逐文件说明:

go_blog/
├── main.go                    # 入口,路由注册,中间件装配
├── config/
│   └── config.go              # 配置加载 / 自动创建(区分操作系统)
├── models/
│   ├── user.go                # 用户模型 + bcrypt
│   ├── article.go             # 文章模型
│   ├── article_tag.go         # 文章-标签关联
│   ├── article_view.go        # 文章阅读统计
│   ├── attachment.go          # 附件模型
│   ├── bot_detector.go        # 机器人流量检测
│   ├── comment.go             # 评论模型
│   ├── comment_config.go      # 评论配置
│   ├── config_cache.go        # 平台配置缓存
│   ├── db.go                  # GORM 初始化、自动迁移
│   ├── nav_link.go            # 导航链接模型
│   ├── seed.go                # 初始数据填充
│   ├── site_setting.go        # 站点设置模型
│   ├── tag.go                 # 标签模型
│   └── upload_config.go       # 上传配置
├── middleware/
│   ├── auth.go                # 登录验证、角色鉴权、语言检测
│   ├── csrf.go                # CSRF 同步器令牌防护
│   ├── https.go               # 请求是否 HTTPS 检测(cookie Secure
│   └── security_headers.go    # 安全响应头(CSP、HSTS、nosniff 等)
├── handlers/
│   ├── helpers.go             # 公共工具函数
│   ├── home.go                # 首页
│   ├── article.go             # 文章详情、文章列表 API
│   ├── auth.go                # 登录
│   ├── login_ratelimit.go     # 登录限速(IP+用户名,5 次失败锁定 15 分钟)
│   ├── admin.go               # 管理后台首页
│   ├── admin_comment.go       # 评论管理
│   ├── admin_user.go          # 用户管理
│   ├── admin_analytics.go     # 阅读统计
│   ├── attachment.go          # 附件上传/删除
│   ├── comment.go             # 评论提交
│   ├── my_articles.go         # 用户文章管理
│   ├── profile.go             # 个人中心
│   ├── rss.go                 # RSS Feed
│   ├── settings.go            # 站点/导航/上传/评论设置
│   └── upload_validator.go    # 上传文件校验(扩展名白名单 + magic-bytes
├── i18n/
│   └── i18n.go                # 中英文翻译映射 + Accept-Language 检测
├── static/
│   ├── css/app.css            # Tailwind 静态构建产物(go:embed 编入二进制)
│   ├── css/input.css          # Tailwind 构建输入(@tailwind 指令)
│   ├── css/markdown.css       # Markdown 排版样式(go:embed 编入二进制)
│   ├── js/markdown.js         # 前端 Markdown 渲染器(BlogMD
│   └── vendor/                # 本地化的第三方前端库(marked/DOMPurify/highlight.js/cropperjs/easymde
├── scripts/
│   └── build_tailwind.sh      # 重新生成 Tailwind CSS(需 Node,见下)
├── templates/
│   ├── layouts/base.html      # 公共布局(导航栏 + 头像下拉菜单 + 页脚)
│   ├── pages/
│   │   ├── home.html          # 首页(瀑布流 + 无限滚动)
│   │   ├── article.html       # 文章详情页
│   │   ├── login.html         # 登录页
│   │   ├── register.html      # 注册页
│   │   ├── profile.html       # 个人中心
│   │   ├── search.html        # 搜索页
│   │   └── 404.html           # 404 页面
│   ├── admin/
│   │   ├── dashboard.html     # 管理后台首页
│   │   ├── article_list.html  # 文章列表
│   │   ├── article_create.html# 文章编辑
│   │   ├── comment_list.html  # 评论审核
│   │   ├── user_list.html     # 用户列表
│   │   ├── user_form.html     # 用户表单
│   │   ├── analytics_views.html    # 阅读统计
│   │   ├── settings_site.html      # 站点设置
│   │   ├── settings_navlinks.html  # 导航链接设置
│   │   ├── settings_upload.html    # 上传设置
│   │   ├── settings_download.html  # 下载设置
│   │   └── settings_comment.html   # 评论设置
│   └── user/
│       ├── my_articles.html   # 我的文章列表
│       └── my_article_form.html # 我的文章编辑
└── win/                       # 运行时数据目录(Windows,自动创建)
    ├── etc/blog_go/
    │   └── config.yaml
    └── srv/blog_go/
        ├── blog.db
        ├── attachments/
        ├── avatars/
        └── logos/

安全加固

基于 2026-08-19 安全审计与网络上线验证(共 25 项发现,P0–P3 均已修复,详见 SECURITY_TODO.md):

  • 认证与会话
    • 会话密钥由 crypto/rand 生成 32 字节随机数;配置文件缺失 secret 时拒绝启动(不再静默回退)
    • Cookie 加固:HttpOnly + SameSite=LaxHTTPS 下自动加 Secure
    • 全站 CSRF 防护(同步器令牌,30+ 表单与 AJAX 全覆盖);登录/注册成功强制会话轮换(防会话固定)
    • 登录限速:按 IP+用户名 5 次失败锁定 15 分钟;用户不存在时也执行 bcrypt 比较,抹平计时侧信道
    • 禁用/锁定/软删用户的会话实时失效;管理员口令 bcrypt cost 12
  • 数据与注入
    • GORM 全参数化查询;管理路由的 :id 先解析为数值再入查询(防字符串条件注入)
    • /uploads 仅白名单挂载子目录,SQLite 数据库文件不可从公网下载;目录列表与路径穿越一律 404
  • 上传安全
    • 扩展名白名单 + 危险扩展名黑名单(.html/.svg/.js 等,防同源 Active Content
    • 内容 magic-bytes 与声明类型一致性校验(gabriel-vasile/mimetype
    • 头像强制解码→256px 缩放→JPEG 重编码后落盘,原始字节一律不落地
  • 输出与传输
    • CSPdefault-src 'self',第三方前端资源已本地化)、X-Frame-Options: DENYX-Content-Type-Options: nosniffReferrer-PolicyPermissions-PolicyHTTPS 下发 HSTS
    • 客户端 IP 解析仅信任 web.trusted_proxies 名单内代理(防 X-Forwarded-For 伪造);RSS 链接使用站点设置的规范地址(防 Host 头污染)

安全回归用例 50+handlers/*_test.gomain_test.gomiddleware/*_test.go),go test -race ./... 全绿。

路由

公开路由

方法 路径 说明
GET / 首页
GET /search 搜索页
GET /api/articles 文章列表 API(无限滚动)
GET /rss/feed RSS 订阅
GET /article/:slug 文章详情
POST /article/:slug/comments 发表评论
GET /login 登录页
POST /login 提交登录
GET /register 注册页
POST /register 提交注册
POST /logout 退出登录
GET /uploads/* 静态文件(头像、附件等)

管理后台(需管理员权限)

方法 路径 说明
GET /admin 管理后台首页
GET /admin/articles 文章列表
GET/POST /admin/articles/new 新建文章
GET/POST /admin/articles/:id/edit 编辑文章
POST /admin/articles/:id/delete 删除文章
POST /admin/articles/attachments 上传附件
POST /admin/articles/attachments/:id/delete 删除附件
GET /admin/articles/:id/attachments 附件列表
GET /admin/comments 评论管理
POST /admin/comments/:id/approve 通过评论
POST /admin/comments/:id/reject 拒绝评论
POST /admin/comments/:id/delete 删除评论
GET /admin/users 用户列表
GET/POST /admin/users/new 新建用户
GET/POST /admin/users/:id/edit 编辑用户
POST /admin/users/:id/delete 删除用户
GET /admin/analytics/views 阅读统计
GET/POST /admin/settings/site 站点设置
GET/POST /admin/settings/navlinks 导航链接设置
GET/POST /admin/settings/upload 上传设置
GET/POST /admin/settings/download 下载设置
GET/POST /admin/settings/comments 评论设置

个人中心(需登录)

方法 路径 说明
GET/POST /profile 编辑个人信息
POST /profile/avatar 上传头像
GET /my/articles 我的文章列表
GET/POST /my/articles/new 新建文章
GET/POST /my/articles/:id/edit 编辑文章
POST /my/articles/:id/delete 删除文章
POST /my/articles/attachments 上传附件
POST /my/articles/attachments/:id/delete 删除附件
GET /my/articles/:id/attachments 附件列表

用户角色

角色 个人中心 我的文章 管理后台
admin
author

许可证

MIT

S
Description
No description provided
Readme
2.3 MiB
0 Stars 1 Watchers 0 Forks
Languages
Go 53.3%
HTML 45.9%
Shell 0.8%