Skip to content

🌐 部署私有 WEB 解密服务

PasswordReset 提供了基于 Docker 的私有 Web 解密服务,管理员可以在内网部署一个 Web 界面,让团队成员通过安全秘钥自助查询当日密码,无需登录服务器。

架构说明

Web 解密服务是无状态的——不需要挂载配置文件,服务仅根据用户传入的安全秘钥和当天日期实时派生密码。

┌──────────────────────────────────────────────────────────┐
│  Docker 容器 (时区: Asia/Shanghai)                        │
│  ┌─────────────────────────────────────────────────────┐ │
│  │  PasswordReset-server (:12397)                       │ │
│  │  ├── /api/password  → 密码查询 API (POST)          │ │
│  │  ├── /api/time      → 服务器时间 (GET)              │ │
│  │  ├── /api/health    → 健康检查 (GET)               │ │
│  │  └── /*             → 前端静态页面 (Vue 3 SPA)     │ │
│  └─────────────────────────────────────────────────────┘ │
│  内置: builtinKey (编译时注入,与客户端绑定)              │
└──────────────────────────────────────────────────────────┘

::: important 两个关键要求

  1. builtinKey 一致:服务端和客户端的 builtinKey 必须相同(由同一源码编译,或构建时传入相同的 BUILTIN_KEY
  2. 时间一致:密码按日期生成,容器时间必须与密码重置服务器时间一致(默认北京时间) :::
  • 无状态:无需挂载配置文件,开箱即用
  • builtinKey 内置:编译时注入二进制,不接受运行时修改,客户端和服务端天然绑定
  • 后端:Go HTTP 服务,接收安全秘钥,结合 builtinKey 和当天日期实时派生密码
  • 前端:Vue 3 单页应用,密码默认脱敏显示,点击复制按钮获取完整密码
  • 安全:服务端日志不记录密码,前端不缓存密码明文

密码生成原理

用户输入安全秘钥 (userKey)

SHA256(builtinKey + ":" + userKey + ":" + 当天日期)

base64 编码 → 最终密码
  • builtinKey:编译时注入,客户端和服务端相同
  • userKey:每用户独立的安全密钥,添加用户时设置
  • 日期:当天 YYYYMMDD(确保每天密码不同)
  • 日期参与 SHA256 运算,不是拼接在密码后面,保证每天密码完全不同

快速部署

公共查询平台

如果不需要私有部署,可以直接使用官方公共查询平台:https://encrypt.liumou.site/

公共平台已内置与官方预编译客户端一致的 builtinKey,直接输入安全秘钥即可查询当日密码,无需任何部署。

TIP

公共平台适合临时查询或小规模使用。如需在内网部署、限制访问来源或自定义时区,请参考下方私有部署方式。

使用公共镜像(推荐)

公共镜像已内置与官方预编译客户端一致的 builtinKey,开箱即用:

bash
docker run -d \
  --name passwordreset-server \
  --restart unless-stopped \
  -p 12397:12397 \
  -e TZ=Asia/Shanghai \
  ccr.ccs.tencentyun.com/passwordreset/server:latest
参数说明
-p 12397:12397宿主机端口:容器端口,可修改左侧宿主机端口
-e TZ容器时区,默认 Asia/Shanghai,影响密码按日生成
无数据库、无配置文件,纯无状态服务

Docker Compose 部署

完整的 Docker Compose 配置见根目录 docker-compose.yml,同目录下 env.sh 文件可直接导入环境变量:

bash
# env.sh
# ===========================================
# PasswordReset Web 解密服务 - 环境变量配置
# ===========================================

# 时区(默认: Asia/Shanghai)
TZ="Asia/Shanghai"
yaml
# =============================================================================
# PasswordReset Web 解密服务
# 访问端口: 12397  (Web 界面 + API)
# 功能: 用户通过安全秘钥自助查询当日密码
# 说明: 无状态服务,无需挂载配置文件,无需数据库
# 使用方式:
#   docker compose up -d
# 环境变量:
#   TZ  时区(默认: Asia/Shanghai),影响密码生成日期
# =============================================================================
services:
  passwordreset:                               # Web 解密服务(前端 SPA + 后端 API)
    image: ccr.ccs.tencentyun.com/passwordreset/server:latest  # 公共镜像
    container_name: passwordreset-server       # 容器名称
    network_mode: bridge                       # 桥接网络
    ports:
      - "12397:12397"                         # 宿主机端口:容器端口
    environment:
      - TZ=${TZ:-Asia/Shanghai}               # 时区设置,影响密码按日生成
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:12397/api/health"]
      interval: 30s                            # 健康检查间隔
      timeout: 10s                             # 检查超时
      retries: 3                              # 重试次数
      start_period: 10s                       # 启动宽限期
    restart: unless-stopped                   # 容器退出策略

部署管理命令

bash
# 启动服务
docker compose up -d

# 查看运行状态
docker compose ps

# 查看实时日志
docker compose logs -f

# 重启服务
docker compose restart

# 停止服务
docker compose down

# 更新到最新镜像
docker compose pull && docker compose up -d

自行构建镜像

如果使用自行编译的客户端(非官方预编译版本),需要使用相同的 BUILTIN_KEY 构建 Web 服务镜像:

bash
# 克隆仓库
git clone https://gitee.com/liumou_site/PasswordReset.git
cd PasswordReset

# 方式1:通过构建参数传入 builtinKey(与客户端编译时相同)
docker build \
  --build-arg BUILTIN_KEY="你的builtinKey-hex字符串" \
  -t passwordreset-server .

# 方式2:通过 builtin.key 文件传入
echo -n "你的builtinKey-hex字符串" > builtin.key
docker build -t passwordreset-server .

# 运行
docker run -d \
  --name passwordreset-server \
  --restart unless-stopped \
  -p 12397:12397 \
  passwordreset-server

WARNING

builtinKey 在编译时注入二进制,客户端和服务端必须使用相同的值才能生成一致的密码。如果使用官方预编译客户端,直接使用公共镜像即可;如果自行编译客户端,构建镜像时必须传入相同的 BUILTIN_KEY

使用方式

  1. 浏览器访问 http://<服务器IP>:12397
  2. 输入安全秘钥(即添加用户时设置的 userKey)
  3. 点击"查询今日密码"
  4. 密码默认脱敏显示(如 20****25),点击 👁 眼睛图标可切换明文/脱敏
  5. 点击"复制密码"按钮获取完整密码到剪贴板

生产环境建议

HTTPS 反向代理

建议在生产环境中使用 Nginx 反向代理并启用 HTTPS:

nginx
server {
    listen 443 ssl;
    server_name password.example.com;

    ssl_certificate     /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    location / {
        proxy_pass http://127.0.0.1:12397;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

安全建议

措施说明
内网部署仅在内网开放,不暴露到公网
HTTPS防止秘钥和密码在传输中被窃听
访问控制通过 Nginx 或防火墙限制来源 IP
日志脱敏服务端日志不记录密码明文
前端脱敏密码默认遮罩显示,需主动点击才可查看明文
时间同步确保容器与密码重置服务器时间一致(默认北京时间)

健康检查

服务提供 /api/health 健康检查端点:

bash
curl http://localhost:12397/api/health
# 返回: {"status":"ok"}

API 参考

POST /api/password

查询当日密码。

请求:

json
{
  "key": "用户安全秘钥"
}

成功响应:

json
{
  "password": "base64编码的SHA256哈希值",
  "date": "2026-05-26"
}

错误响应:

json
{
  "error": "缺少 key 参数"
}

GET /api/time

获取服务器时间。

响应:

json
{
  "timezone": "CST",
  "date": "2026-05-26",
  "time": "14:30:00",
  "unix": 1748238600,
  "display_name": "2026-05-26 14:30:00"
}

GET /api/health

健康检查端点。

响应:

json
{
  "status": "ok"
}

常见问题

Q: 为什么不需要在运行时传入密钥?

A: builtinKey 在编译时已注入二进制文件中,不需要运行时注入。公共镜像的 builtinKey 与官方预编译客户端一致,直接使用即可。只有自行编译客户端时,才需要在构建镜像时传入相同的 BUILTIN_KEY

Q: 时区不一致会怎样?

A: 密码基于日期参与 SHA256 运算生成(SHA256(builtinKey:userKey:YYYYMMDD))。如果容器时区与密码重置服务器不同,可能导致跨日时查询到的密码不匹配。例如服务器在北京时间 5 月 26 日 00:30 重置了密码,但 UTC 时区的容器仍认为是 5 月 25 日,查询结果就会错误。公共镜像默认设置为北京时间(Asia/Shanghai),一般无需修改。

Q: 忘记安全秘钥怎么办?

A: 安全秘钥即添加用户时设置的 userKey。如果遗忘,无法通过系统恢复,需要重新添加用户并设置新的密钥。

Q: 多人使用是否安全?

A: 每个用户使用各自的安全密钥(userKey)查询对应的密码,不同密钥查询不同用户的密码结果。一个用户的密钥泄露不影响其他用户。建议在内网部署并通过 HTTPS + IP 白名单加强安全性。

基于 MIT 许可发布