Skip to content

密码管理

在 Potato 中配置 PBKDF2-SHA256 密码哈希、管理员 CLI/API 重置、用户自助的令牌重置流程,以及 SQLite 或 PostgreSQL 凭据存储。

v2.4.0 新增

Potato 的认证系统使用 PBKDF2-SHA256,迭代 10 万次,并为每个用户生成独立的 salt —— 这也是 NIST 推荐的密码存储做法。本页介绍密码如何存储、如何重置,以及如何让凭据在服务器重启后依然有效。

安全实现

密码以 salt$hash 格式存储:

  • 32 个十六进制字符的 salt,每个用户各不相同
  • salt + password 的 SHA-256 哈希,64 个字符
  • 通过 hmac.compare_digest 做常数时间比较,防止时序攻击

如果 user_config.jsonl 文件里还存着明文密码,Potato 加载时会自动用新的 salt 重新哈希,不需要手动迁移。

默认配置

默认情况下 Potato 使用内存认证,标注者必须写在配置里:

yaml
authentication:
  method: in_memory
  require_password: true
 
user_config:
  users:
    - username: "annotator1"
      password: "initial-password"   # will be hashed on first load
    - username: "annotator2"
      password: "initial-password"

持久化凭据

内存中的凭据重启后就没了。要持久保存,用文件或数据库后端。

基于文件的持久化

yaml
authentication:
  method: in_memory
  user_config_path: /shared/path/to/user_config.jsonl

Potato 会把哈希后的凭据写进这个文件,重启时再读回来 —— 会话期间设置或修改的密码可以跨重启保留。

数据库后端

SQLite(不需要额外依赖):

yaml
authentication:
  method: database
  database_url: "sqlite:///auth/users.db"

PostgreSQL(需要 psycopg2-binary):

yaml
authentication:
  method: database
  database_url: "postgresql://user:password@localhost:5432/potato_auth"

数据库表会在首次启动时自动创建。

注意: method: databaseuser_config_path 互斥,只能选一种持久化方式。

重置密码

管理员 CLI

从命令行重置密码:

bash
# Reset a specific user's password
potato reset-password config.yaml --username annotator1
 
# Prompted for new password interactively

管理员 API

用 API key 以程序方式重置:

bash
curl -X POST http://localhost:8000/admin/reset_password \
  -H "X-API-Key: $ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"username": "annotator1", "new_password": "new-secure-password"}'

用户自助的令牌重置

Potato 支持由用户发起的重置流程。用户访问 /forgot-password,输入用户名,拿到一个一次性的重置令牌,再访问 /reset/<token> 设置新密码。

令牌有效期为 24 小时,且只能使用一次。Potato 不发邮件,重置链接由管理员手动发给用户。

在配置中启用:

yaml
authentication:
  method: database
  database_url: "sqlite:///auth/users.db"
  allow_password_reset: true
  reset_token_ttl_hours: 24

管理员操作流程:

bash
# Generate a reset token for a user
curl -X POST http://localhost:8000/admin/generate_reset_token \
  -H "X-API-Key: $ADMIN_API_KEY" \
  -d '{"username": "annotator1"}'
 
# Returns: {"reset_url": "https://your-server.com/reset/abc123..."}
# Share this URL with the annotator

免密模式

课堂演示、快速小规模研究,或者使用外部认证(MTurk、Prolific)的任务,可以完全关掉密码:

yaml
authentication:
  method: in_memory
  require_password: false

标注者输入任意用户名即可登录,不会出现密码输入框。涉及敏感数据或需要确认身份的任务不建议这么做。

详见免密登录

完整参考

yaml
authentication:
  method: in_memory       # in_memory | database | oauth | clerk
 
  # In-memory options
  require_password: true
  user_config_path: path/to/users.jsonl   # optional persistence
 
  # Database options (mutually exclusive with user_config_path)
  database_url: "sqlite:///auth/users.db"
 
  # Self-service reset
  allow_password_reset: true
  reset_token_ttl_hours: 24
 
user_config:
  users:
    - username: "researcher"
      password: "secure-passphrase"
      role: admin
    - username: "annotator1"
      password: "initial-pass"
      role: annotator

延伸阅读

有关实现详情,请参阅源文档