feat: passwordHasher 可注入 — bcrypt 不再是 Shrimp 核心硬依赖

新增 IPasswordHasher 抽象 + bcryptHasher(默认,lazy import)+ plainHasher
(测试用)。Password 字段 reqFilter 和 UserModule.verifyPassword 都走
`Shrimp.passwordHasher`,消费方在启动期换实现就能彻底跳过 bcrypt。

  import { Shrimp, plainHasher } from "shrimp-server"
  Shrimp.passwordHasher = plainHasher

测试覆盖默认值、plain 端到端登录、自定义 hasher 被调用。
This commit is contained in:
2026-05-23 16:57:27 +08:00
parent 36326ac26b
commit 36b71bd38e
5 changed files with 150 additions and 11 deletions
+21
View File
@@ -266,6 +266,27 @@ ShrimpTableModule.registerTypeHandler('phone', {
### 自定义 type 的前端渲染
后端只声明 `type: 'fieldGoodsPicker'` 即可,前端在 `hand-admin/src/module/fields/` 放一个 `FieldGoodsPicker.vue`,会按命名约定自动注册(`Field*.vue` → `'field' + *`)。
### 替换密码哈希(passwordHasher)
默认 Password 字段写入时走 bcrypt,登录时 `UserModule.verifyPassword` 也走 bcrypt。bcrypt 是 lazy import 的——不真正调用 hash/verify 就不会 require,所以**不需要**密码功能的项目可以根本不装 bcrypt。
需要替换(测试用明文 / 改 argon2 / 接入老系统的 SHA256)时,在启动期改一行:
```ts
import { Shrimp, plainHasher } from "shrimp-server"
// 测试 / 开发
Shrimp.passwordHasher = plainHasher
// 或自定义
Shrimp.passwordHasher = {
async hash(plain) { /* ... */ return hashed },
async verify(plain, hashed) { /* ... */ return ok },
}
```
`Password` 字段 reqFilter 和 `UserModule.verifyPassword` 都会走新 hasher。**plainHasher 仅用于测试/开发**,不要在生产环境用。
---
## 6. 用 operator 拿到当前登录用户