bknd用户创建技能Skill bknd-create-user

此技能用于在Bknd平台中创建和管理用户账户,支持通过种子函数初始化管理员账户、使用SDK和REST API编程创建、管理员面板手动创建,并包含角色分配、用户字段扩展和密码安全处理。关键词:Bknd, 用户创建, 账户管理, 认证, 授权, 种子函数, SDK, REST API, 角色分配, 密码哈希。

低代码开发 0 次安装 0 次浏览 更新于 3/9/2026

名称: bknd-create-user 描述: 在Bknd中编程创建新用户账户时使用。涵盖种子函数中的auth.createUser()、通过SDK/REST API注册、通过数据API创建用户、管理员面板用户创建和角色分配。

创建用户

通过种子函数、SDK、REST API或管理员面板在Bknd中创建新用户账户。

先决条件

  • Bknd项目运行中(本地或部署)
  • 认证模块启用(auth.enabled: true
  • 密码策略配置(默认启用)
  • 对于角色分配:在认证配置中定义角色

何时使用UI模式

  • 在开发过程中创建管理员/测试用户
  • 非技术管理员手动管理用户
  • 一次性用户创建

UI步骤: 管理员面板 > 认证 > 用户 > 点击“+” > 填写邮箱/密码 > 选择角色 > 保存

何时使用代码模式

  • 首次部署时种子初始管理员用户
  • 在服务器代码中编程创建用户
  • 前端用户注册流程
  • 自动化用户供应

代码方法

方法1:种子函数(推荐用于初始用户)

通过种子函数在应用首次启动时创建用户:

import { serve } from "bknd/adapter/bun";
import { em, entity, text } from "bknd";

const schema = em({
  posts: entity("posts", { title: text().required() }),
});

serve({
  connection: { url: "file:data.db" },
  config: {
    data: schema.toJSON(),
    auth: {
      enabled: true,
      jwt: { secret: process.env.JWT_SECRET || "dev-secret" },
      roles: {
        admin: { implicit_allow: true },
        user: { implicit_allow: false },
      },
    },
  },
  options: {
    seed: async (ctx) => {
      // 在首次运行时创建管理员用户
      await ctx.app.module.auth.createUser({
        email: "admin@example.com",
        password: "securepassword123",
        role: "admin",
      });
      console.log("管理员用户已创建");
    },
  },
});

种子函数注意点:

  • 仅在数据库为空时首次启动运行
  • 拥有对ctx.app.module.auth的完全访问权限
  • 适合创建初始管理员账户

方法2:服务器端createUser()

在服务器代码中编程创建用户(插件、流程、自定义端点):

import { getApi } from "bknd";

// 在插件、流程或自定义端点处理程序中
async function createAdminUser(app) {
  const user = await app.module.auth.createUser({
    email: "newadmin@example.com",
    password: "securepassword123",
    role: "admin",
  });

  console.log("创建的用户:", user.id, user.email);
  return user;
}

// 包含额外字段(如果用户实体有自定义字段)
async function createUserWithProfile(app) {
  const user = await app.module.auth.createUser({
    email: "user@example.com",
    password: "password123",
    role: "user",
    name: "John Doe",        // 自定义字段
    avatar: "https://...",   // 自定义字段
  });
  return user;
}

createUser() 签名:

type CreateUserPayload = {
  email: string;      // 必需:用户邮箱
  password: string;   // 必需:明文密码(将被哈希)
  role?: string;      // 可选:必须在auth.roles中存在
  [key: string]: any; // 用户实体的额外字段
};

// 返回创建的用户记录
async createUser(payload: CreateUserPayload): Promise<User>

方法3:SDK注册(客户端)

通过前端用户自注册:

import { Api } from "bknd";

const api = new Api({
  host: "http://localhost:7654",
  storage: localStorage,  // 用于令牌持久化
});

// 注册新用户
const { ok, data, error } = await api.auth.register("password", {
  email: "newuser@example.com",
  password: "securepassword123",
});

if (ok) {
  console.log("已注册:", data.user);
  console.log("令牌:", data.token);
  // 用户现已登录,令牌存储在localStorage
} else {
  console.error("注册失败:", error);
}

注册注意点:

  • 需要auth.allow_register: true(默认)
  • 自动分配auth.default_role_register角色
  • 返回JWT令牌(注册后用户登录)
  • 仅接受邮箱/密码;额外字段需要单独更新

方法4:REST API注册

# 通过REST API注册
curl -X POST http://localhost:7654/api/auth/password/register \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "securepassword123"}'

响应:

{
  "user": {
    "id": 1,
    "email": "user@example.com",
    "role": "user"
  },
  "token": "eyJhbGciOiJIUzI1NiIs..."
}

方法5:数据API(管理员创建用户)

管理员可通过数据API直接创建用户(需要认证+管理员角色):

// 作为认证管理员
const { ok, data } = await api.data.createOne("users", {
  email: "managed@example.com",
  strategy: "password",
  strategy_value: "HASHED_PASSWORD",  // 必须预哈希!
  role: "user",
});

警告: 数据API需要预哈希密码。使用createUser()或注册以进行正确的密码处理。

React集成

注册表单

import { useApp } from "bknd/react";
import { useState } from "react";

function RegisterForm() {
  const { api } = useApp();
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setLoading(true);
    setError(null);

    const { ok, data, error: apiError } = await api.auth.register("password", {
      email,
      password,
    });

    setLoading(false);

    if (ok) {
      console.log("已注册:", data.user);
      // 重定向到仪表板或显示成功
    } else {
      setError(apiError?.message || "注册失败");
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="邮箱"
        required
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="密码"
        minLength={8}
        required
      />
      <button type="submit" disabled={loading}>
        {loading ? "创建账户中..." : "注册"}
      </button>
      {error && <p className="error">{error}</p>}
    </form>
  );
}

使用useAuth钩子

import { useAuth } from "@bknd/react";

function AuthStatus() {
  const { user, isLoading, register, logout } = useAuth();

  if (isLoading) return <div>加载中...</div>;

  if (!user) {
    return (
      <button onClick={() => register("password", {
        email: "new@example.com",
        password: "password123"
      })}>
        创建账户
      </button>
    );
  }

  return (
    <div>
      <p>欢迎, {user.email}</p>
      <button onClick={logout}>登出</button>
    </div>
  );
}

配置选项

启用/禁用注册

{
  auth: {
    enabled: true,
    allow_register: true,  // 设置为false以禁用自注册
    default_role_register: "user",  // 注册时分配的角色
  },
}

密码要求

{
  auth: {
    strategies: {
      password: {
        type: "password",
        enabled: true,
        config: {
          hashing: "bcrypt",   // "plain" | "sha256" | "bcrypt"
          rounds: 4,           // bcrypt轮数(1-10)
          minLength: 8,        // 最小密码长度
        },
      },
    },
  },
}

定义角色用于分配

{
  auth: {
    roles: {
      admin: {
        implicit_allow: true,  // 可以做所有事情
      },
      editor: {
        implicit_allow: false,
        permissions: [
          { permission: "data.posts.read", effect: "allow" },
          { permission: "data.posts.create", effect: "allow" },
          { permission: "data.posts.update", effect: "allow" },
        ],
      },
      user: {
        implicit_allow: false,
        permissions: [
          { permission: "data.posts.read", effect: "allow" },
        ],
      },
    },
    default_role_register: "user",  // 新注册获得此角色
  },
}

扩展用户实体

向用户添加自定义字段:

import { em, entity, text, date } from "bknd";

const schema = em({
  users: entity("users", {
    email: text().required().unique(),
    name: text(),
    avatar: text(),
    bio: text(),
    created_at: date({ default_value: "now" }),
  }),
});

// 在配置中
{
  config: {
    data: schema.toJSON(),
    auth: { enabled: true, /* ... */ },
  },
}

注意: strategystrategy_value字段由认证系统管理 - 不要直接修改。

常见问题

注册被禁用

问题: 注册不被允许错误

修复: 启用注册:

{ auth: { allow_register: true } }

角色未找到

问题: 角色"admin"未找到错误

修复: 在分配前在配置中定义角色:

{
  auth: {
    roles: {
      admin: { implicit_allow: true },
    },
  },
}

用户已存在

问题: 用户已存在唯一约束失败

修复: 创建前检查或处理错误:

// SDK注册自动处理此问题
const { ok, error } = await api.auth.register("password", { email, password });
if (!ok && error?.message?.includes("exists")) {
  console.log("邮箱已注册");
}

// 服务器端:先检查
const { data: exists } = await api.data.exists("users", {
  email: { $eq: email },
});
if (!exists.exists) {
  await app.module.auth.createUser({ email, password });
}

弱JWT密钥

问题: 没有密钥无法签名JWT或安全警告

修复: 设置强JWT密钥:

{
  auth: {
    jwt: {
      secret: process.env.JWT_SECRET,  // 使用环境变量,至少256位
    },
  },
}

密码未哈希(数据API)

问题: 通过数据API创建后用户无法登录

原因: 数据API不自动哈希密码

修复: 使用createUser()或注册代替:

// 错误 - 密码未哈希
await api.data.createOne("users", { email, password: "plain" });

// 正确 - 使用认证模块
await app.module.auth.createUser({ email, password: "plain" });

额外字段未保存

问题: 注册后自定义字段未包含

原因: 注册仅接受邮箱/密码

修复: 注册后更新用户:

const { data } = await api.auth.register("password", { email, password });

// 更新额外字段
await api.data.updateOne("users", data.user.id, {
  name: "John Doe",
  avatar: "https://...",
});

验证

创建用户后,验证:

// SDK - 注册后检查当前用户
const { data } = await api.auth.me();
console.log("当前用户:", data?.user);

// 服务器端 - 读取
const { data: user } = await api.data.readOneBy("users", {
  where: { email: { $eq: "user@example.com" } },
});
console.log("创建的用户:", user);

或通过管理员面板:管理员面板 > 认证 > 用户 > 在列表中查找新用户。

注意事项

应做:

  • 使用createUser()或注册以进行正确的密码哈希
  • 使用种子函数用于初始管理员用户
  • 在生产环境中设置强JWT密钥
  • 在分配前定义角色
  • 在生产环境中使用bcrypt哈希

不应做:

  • 通过数据API创建用户(密码不会被正确哈希)
  • 存储明文密码
  • 在生产环境中使用弱JWT密钥
  • 分配不存在的角色
  • 直接修改strategystrategy_value字段

相关技能

  • bknd-setup-auth - 初始化认证系统
  • bknd-login-flow - 实现登录/登出功能
  • bknd-registration - 设置用户注册流程
  • bknd-create-role - 定义用于用户分配的角色
  • bknd-assign-permissions - 配置角色权限