Skip to content

安全体系

Zenith Admin 内置了多层安全防护能力,涵盖 IP 访问控制、账号锁定、密码策略、验证码及注册开关,均可通过系统配置页面在运行时动态调整。


IP 访问控制

通过 ipAccessMiddleware 对所有 /api/* 请求进行 IP 过滤,支持白名单黑名单两种模式(可同时启用,黑名单优先执行)。

配置项

在后台「系统设置 → IP 访问控制」页面配置(对应 system_configs 表中的以下 key):

配置 Key类型说明
ip_whitelist_enabledboolean是否启用白名单。启用后只有名单内的 IP 可访问
ip_whiteliststring (JSON 数组)白名单 IP 列表,如 ["192.168.1.0/24", "10.0.0.1"]
ip_blacklist_enabledboolean是否启用黑名单。启用后名单内 IP 访问将收到 403
ip_blackliststring (JSON 数组)黑名单 IP 列表,支持单 IP 与 CIDR 网段

工作机制

请求进入 /api/*

  ├── 免检路径(直接放行):
  │   /api/auth/login、/api/auth/captcha、/api/auth/register
  │   /api/auth/refresh、/api/oauth/*

  ├── 两者均未启用 → 直接放行

  ├── 黑名单已启用 → 命中则 403

  └── 白名单已启用 → 未命中则 403
  • IP 来源优先从 X-Forwarded-For 请求头中读取(取第一个值),其次读取 X-Real-IP
  • 支持 CIDR 网段匹配(如 192.168.1.0/24),基于 ip-range-check 库实现
  • 配置缓存 30 秒,修改后台配置后最多延迟 30 秒生效

Nginx 反代注意:确保 Nginx 已正确设置 X-Real-IPX-Forwarded-For,否则后端收到的将是内网 IP。


账号锁定

连续登录失败超过阈值后,账号会被自动锁定一段时间,有效防止暴力破解。

相关配置项

配置 Key类型默认值说明
login_max_attemptsnumber10最大失败次数,超过后自动锁定
login_lock_duration_minutesnumber30锁定持续时长(分钟)

工作机制

  • 失败计数以 loginAttempts:{username} 为 key 存储于 Redis,服务重启后不重置
  • 锁定到期后自动解除
  • 管理员可在「用户管理」列表中点击「解除锁定」按钮,提前解除指定账号的锁定状态(调用 POST /api/users/:id/unlock

密码策略

从 v0.1.4 起,支持通过系统配置控制密码复杂度要求与过期策略。

复杂度配置项

配置 Key类型默认值说明
password_min_lengthnumber6密码最小长度
password_require_uppercasebooleanfalse是否必须包含大写字母
password_require_special_charbooleanfalse是否必须包含特殊字符(!@#$%^&* 等)

密码复杂度在以下场景触发校验:

  • 用户创建(管理员操作)
  • 用户修改个人密码
  • 重置密码

密码过期

配置 Key类型默认值说明
password_expiry_enabledbooleanfalse是否开启密码过期强制重置。开启后,当密码超期未更新,登录时将强制跳转修改密码页
password_expiry_daysnumber90密码有效期天数,仅在 password_expiry_enabledtrue 时生效

过期流程

  1. 用户登录时,若 password_expiry_enabled = true,后端计算 passwordUpdatedAt + password_expiry_days 是否早于当前时间
  2. 若已过期,登录接口不返回 token,而是返回特殊 code(password_expired)和临时 token
  3. 前端检测到特殊 code 后,弹出「强制修改密码」弹窗
  4. 用户通过临时 token 完成密码修改后,方可正常使用系统

登录验证码

配置 Key类型默认值
captcha_enabledbooleanfalse

启用后,登录页自动显示图形验证码输入框。验证码通过 GET /api/auth/captcha 获取(返回 Base64 图片 + captchaId),登录时需同时提交 captchaId 和用户输入的验证码文本,后端校验后自动失效。


注册开关

配置 Key类型默认值
allow_registrationbooleanfalse
  • false:登录页不显示「注册」入口,POST /api/auth/register 返回 403
  • true:开放注册,登录页显示「注册账号」链接

生产建议:如非公开注册场景,建议保持 allow_registration = false


安全相关接口速查

接口说明
GET /api/auth/captcha获取验证码(返回 Base64 图片 + captchaId)
POST /api/auth/register开放注册(受 allow_registration 控制)
POST /api/users/{id}/unlock管理员解除账号锁定
PUT /api/auth/password当前用户修改密码
POST /api/auth/forgot-password发送找回密码邮件
POST /api/auth/reset-password使用重置 token 设置新密码
PUT /api/users/{id}/password管理员修改指定用户密码

CSRF 防护

基于 hono/csrf 中间件校验请求的 Origin 头,防止第三方网站伪造表单或 AJAX 请求。

配置

通过环境变量 ALLOWED_ORIGINS 配置允许的来源白名单(在 .env 中设置):

dotenv
# 留空 = 开发模式,不限制来源
ALLOWED_ORIGINS=

# 生产环境示例(逗号分隔)
ALLOWED_ORIGINS=https://admin.example.com,https://app.example.com

放行规则

  • 请求无 Origin 头(服务端调用、Postman、curl)→ ✅ 直接放行
  • ALLOWED_ORIGINS 为空(开发模式)→ ✅ 直接放行
  • Origin 在白名单中 → ✅ 放行
  • Origin 不在白名单中 → ❌ 403 Forbidden

生产建议:务必配置 ALLOWED_ORIGINS,否则任何来源的请求均可通过 CSRF 检查。


接口限流

基于 hono-rate-limiter + Redis 对高危接口进行限流,防止暴力破解和滥用。

当前限流策略

  • POST /api/auth/login:15 分钟内最多 10 次,用于防暴力破解密码
  • GET /api/auth/captcha:1 分钟内最多 30 次,用于防验证码刷取
  • POST /api/auth/register:1 小时内最多 5 次,用于防滥用注册
  • POST /api/auth/forgot-password:1 小时内最多 5 次,用于防账号枚举
  • POST /api/auth/reset-password:1 小时内最多 5 次,用于防重置密码滥用

超过限制时返回:

json
{
  "code": 429,
  "message": "操作过于频繁,请稍后再试",
  "data": null
}

实现细节

  • 限流计数以 IP 地址为 key(X-Forwarded-For 优先,其次 X-Real-IP,fallback 0.0.0.0
  • 计数器存储在 Redis(key 格式:{prefix}rl:{ip}),服务重启后持续计数
  • 实现位置:packages/server/src/middleware/rate-limit.ts

反代注意:确保 Nginx 正确透传 X-Forwarded-ForX-Real-IP,否则所有请求将共享同一计数(fallback 0.0.0.0),导致正常请求被误限。

Built with VitePress for local documentation preview.