API 设计:22 个接口的分层与安全体系

2026年6月18日 blogTech 7 分钟阅读 1 次阅读
📖 文章摘要

22 个 API 端点分公开/网盘/管理三层。本文详解文章列表分页、全文搜索、JWT 认证和安全机制的设计与实现。

API 设计:22 个端点三层架构

博客后端共 22 个 API 端点,分为公开接口、网盘接口、管理接口三个层级。

层级 1:公开接口(9 个)

无需认证,任何人都可访问:

方法 路径 说明
GET /api/articles 文章列表(分页 + 分类/标签筛选)
GET /api/articles/{slug} 文章详情(自动 +1 阅读量)
GET /api/categories 分类列表
GET /api/tags 标签列表
GET /api/search?q= 全文搜索(标题 + 正文 + 摘要)
POST /api/comments 提交评论
GET /api/comments/{id} 评论列表
GET /api/feed/rss RSS 订阅
GET /api/site 站点信息

文章列表 API 实现

@router.get("", response_model=dict)
def list_articles(
    page: int = Query(1, ge=1),
    size: int = Query(24, ge=1, le=50),
    category: str = None,
    tag: str = None,
    db: Session = Depends(get_db),
):
    query = db.query(Article).filter(Article.is_published == True)
    if category:
        query = query.join(Article.category).filter(Category.slug == category)
    query = query.order_by(desc(Article.is_top), desc(Article.published_at))
    total = query.count()
    items = query.offset((page - 1) * size).limit(size).all()
    return {
        "items": [ArticleListItem.model_validate(a) for a in items],
        "total": total, "page": page, "size": size,
        "pages": (total + size - 1) // size,
    }

关键点:

  • 使用 ArticleListItem.model_validate(a) 通过 Pydantic schema 序列化,确保响应格式一致
  • model_validate 在 Pydantic v2 中是严格模式——字段类型不匹配会直接报错
  • is_top 降序排列保证置顶文章始终在前面

全文搜索实现

query = db.query(Article).filter(
    Article.is_published == True,
    or_(
        Article.title.ilike(f"%{q}%"),
        Article.content_md.ilike(f"%{q}%"),
        Article.summary.ilike(f"%{q}%"),
    ),
)

SQLite 的 ILIKE 支持大小写不敏感匹配,虽然在大数据量下性能不佳,但对几百篇文章的博客完全够用。

层级 2:网盘接口(6 个)

网盘功能需要双重验证(见第 8 篇文章详解):

方法 路径 认证
POST /api/pan/upload 管理员密码
POST /api/pan/{id}/verify 文件密码
GET /api/pan/{id}/download Token(5 分钟有效)
GET /api/pan JWT
GET /api/pan/{id}/logs JWT
DELETE /api/pan/{id} JWT

层级 3:管理接口(7 个)

所有管理接口通过 JWT 认证:

方法 路径 说明
POST /api/auth/login 登录
GET/POST/PUT/DELETE /api/admin/articles 文章 CRUD
PATCH /api/admin/articles/{id}/publish 发布/下架
GET/POST/DELETE /api/admin/categories 分类管理
GET/POST/DELETE /api/admin/tags 标签管理
GET/POST /api/admin/comments 评论审核
POST /api/admin/upload 图片上传
PUT /api/admin/site 站点配置

JWT 认证实现

def create_token(admin_id: int) -> str:
    expire = datetime.now(timezone.utc) + timedelta(days=7)
    payload = {"sub": str(admin_id), "exp": expire}
    return jwt.encode(payload, SECRET_KEY, algorithm="HS256")

def get_current_admin(credentials, db) -> Admin:
    payload = jwt.decode(credentials, SECRET_KEY, algorithms=["HS256"])
    admin_id = int(payload.get("sub"))
    admin = db.query(Admin).filter(Admin.id == admin_id).first()
    if not admin:
        raise HTTPException(401)
    return admin

认证流程:

  1. 前端登录 → 后端签发 JWT(存 cookie)
  2. 每次 API 请求携带 JWT
  3. 管理接口通过 Depends(get_current_admin) 自动拦截未认证请求
  4. 前端 Axios 响应拦截器检测 401 → 清除 cookie → 跳转登录页

安全设计总结

  • JWT 7 天有效期,无 refresh token 机制(单用户博客简化处理)
  • 密码 SHA256 存储(非加盐,权衡安全性 vs 兼容性)
  • 评论默认隐藏,需要管理员审核通过才显示
  • 网盘双重验证:密码 → 5 分钟有效 token → 文件
  • 后端服务绑定 127.0.0.1,不对外暴露端口
最后更新:2026年6月29日CC BY-NC-SA 4.0

评论

暂无评论,来写第一条吧

© 2026 My Blog. Built with Nuxt.js + FastAPI.