news 2026/9/14 10:41:01

NocoBase 扩展认证类型实战:从 Auth/BaseAuth 内核机制到客户端 registerType 注册全链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
NocoBase 扩展认证类型实战:从 Auth/BaseAuth 内核机制到客户端 registerType 注册全链路

NocoBase 扩展认证类型实战:从 Auth/BaseAuth 内核机制到客户端 registerType 注册全链路

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

本篇围绕 NocoBase「扩展认证类型」的完整开发流程展开,覆盖两类认证(不依赖第三方回调、依赖第三方回调)的标准时序,以及如何继承内核Auth/BaseAuth抽象类、复用 JWT 鉴权逻辑、借助AuthModel处理用户数据、通过AuthManager.registerTypes注册服务端类型与客户端registerType注册 UI 组件。读完你将能够独立完成一个自定义登录插件(如短信、OIDC、SAML),并理解 NocoBase 认证中间件、X-Authenticator头、users/authenticators/usersAuthenticators三表协作的底层实现。

认证模型:两种类型的标准时序

NocoBase 支持按需要扩展用户认证类型。从实现角度看,认证一般分为两类:

  • 不依赖第三方回调:在 NocoBase 应用内完成身份判断,如密码登录、短信登录。
  • 依赖第三方回调:由第三方服务判断用户身份,并将结果通过回调通知 NocoBase,如 OIDC、SAML。

两者在 NocoBase 中的认证流程基本如下。

不依赖第三方回调

  1. 客户端使用 NocoBase SDK 调用登录接口api.auth.signIn(),请求登录接口auth:signIn,同时把当前使用的认证器标识通过请求头X-Authenticator携带给后端。该请求头的键名由内核在服务端启动时注入——从源码结构看,application.ts 中将authKey: 'X-Authenticator'写入AuthManager选项。
  2. auth:signIn接口根据请求头中的认证器标识,转发到认证器对应的认证类型,由该认证类型注册的认证类中的validate方法进行相应的逻辑处理。
  3. 客户端从auth:signIn接口响应中拿到用户信息和认证token,将token保存到 Local Storage,完成登录。这一步由 SDK 内部自动完成处理。

auth:signIn等接口本身就是内核注册的标准资源操作,定义在 actions.ts 中:signIn先做来源校验再调用ctx.auth.signIn()signOut调用ctx.auth.signOut()并派发auth:signOut事件,check则直接返回当前用户(并对users集合中标记hidden的字段做过滤)。

依赖第三方回调

  1. 客户端通过自己注册的接口(比如auth:getAuthUrl)获取第三方登录 URL,并按协议携带应用名称、认证器标识等信息。
  2. 跳转到第三方 URL 完成登录,第三方服务调用 NocoBase 应用的回调接口(需要自己注册,比如auth:redirect),返回认证结果,同时返回应用名称、认证器标识等信息。
  3. 回调接口方法解析参数获得认证器标识,通过AuthManager获取对应的认证类,主动调用auth.signIn()方法。auth.signIn()会调用validate()方法处理鉴权逻辑。
  4. 回调方法拿到认证token,再 302 跳转回前端页面,并在 URL 参数带上token和认证器标识,?authenticator=xxx&token=yyy

下面介绍如何注册服务端接口和客户端用户界面。

服务端:认证接口

NocoBase 内核提供了扩展认证类型的注册和管理。扩展登录插件的核心逻辑处理,需要继承内核的Auth抽象类,并对相应的标准接口进行实现。完整 API 参考 Auth。

Auth抽象类定义在 auth.ts 中,其抽象方法与构造配置为:

import { Auth } from '@nocobase/auth'; class CustomAuth extends Auth { set user(user) {} get user() {} async check() {} async signIn() {} }

从源码结构看,Auth构造入参类型为AuthConfig = { authenticator: Authenticator; options: Record<string, any>; ctx: Context },即认证实例在创建时已经绑定了具体的认证器(authenticator)与请求上下文(ctx),因此认证类内部可以直接访问认证器配置与ctx.db。除文档列出的check/signIn外,内核还约定了checkToken()signUp()signOut()syncCookies()等接口,并定义了统一错误码AuthErrorCode(如EMPTY_TOKENEXPIRED_TOKENINVALID_TOKENNOT_EXIST_USER等),便于各认证类型抛出语义化错误。

内核也注册了用户认证相关的基本资源操作。

API说明
auth:check判断用户是否登录
auth:signIn登录
auth:signUp注册
auth:signOut注销登录

多数情况下,扩展的用户认证类型也可以沿用现有的 JWT 鉴权逻辑来生成用户访问 API 的凭证。内核的BaseAuth类对Auth抽象类做了基础实现,参考 BaseAuth。插件可以直接继承BaseAuth类以便复用部分逻辑代码,降低开发成本。

import { BaseAuth } from '@nocobase/auth'; class CustomAuth extends BaseAuth { constructor(config: AuthConfig) { // 设置用户数据表 const userCollection = config.ctx.db.getCollection('users'); super({ ...config, userCollection }); } // 实现用户认证逻辑 async validate() {} }

BaseAuth 的 JWT 复用逻辑

BaseAuth定义在 base/auth.ts。从源码结构看,它把「认证(validate)」与「发证(sign token)」解耦:

  • 构造时必须传入userCollection,用于userRepository查询用户。
  • validate()默认返回null,由子类覆写完成真正的身份核验并返回Model用户。
  • signIn()是完整登录链:先调用validate()得到用户,若失败抛出 401(NOT_EXIST_USER),随后调用signNewToken(user.id)生成 JWT,再setAuthCookies/setSessionCookies写入浏览器 Cookie,最终返回{ user, token }
  • check()/checkToken()负责校验请求携带的 JWT:解码、按jti查询黑名单、比对signInTime/iat判断是否过期,并在 token 过期但未超限时通过tokenController.renew(jti)完成无感续期,把新 token 写入x-new-token响应头与 Cookie。
  • signOut()会清空认证 Cookie、删除用户角色与用户缓存,并将当前 token 加入黑名单(jwt.block)。

这套逻辑由AuthManager注入的jwtJwtService)与tokenController驱动,意味着子类只需关注「如何核验身份」,发凭证、会话续期、登出失效全部由基类兜底。

认证中间件与 X-Authenticator 解析

请求如何路由到具体认证类?核心在 auth-manager.ts 的middleware()

  1. 从请求头读取authKey(即X-Authenticator)得到headerAuthenticator;若没有,则回退到 Cookie 中的authenticator,再回退到默认认证器。
  2. 通过authManager.get(name, ctx)依据认证器名创建对应认证实例并挂载到ctx.auth
  3. 调用ctx.auth.skipCheck()判断是否可以跳过鉴权(如公开接口、optionalAuth、关闭 ACL 等),否则调用ctx.auth.check()校验用户并写入ctx.auth.user

AuthManager.get()会先查内置认证器(registerBuiltInAuthenticator注册),未命中则通过storerauthenticators集合加载,最终调用createAuth依据authType取出对应认证类构造函数并new出实例——找不到类型时会抛出AuthType [xxx] is not found.

服务端:用户数据

在实现用户认证逻辑时,通常涉及用户数据处理。在 NocoBase 应用中,默认情况下相关的表定义为:

数据表作用插件
users存储用户信息,邮箱、昵称和密码等用户插件 (@nocobase/plugin-users)
authenticators存储认证器(认证类型实体)信息,对应认证类型和配置用户认证插件 (@nocobase/plugin-auth)
usersAuthenticators关联用户和认证器,保存用户在对应认证器下的信息用户认证插件 (@nocobase/plugin-auth)

这三张集合的定义分别位于@nocobase/plugin-auth:authenticators.ts 与 users-authenticators.ts。

从源码结构看:

  • authenticators集合以name为唯一键(unique: true),并携带authTypetitledescription、JSON 类型的options、布尔enabled;其usersbelongsToMany关联,through: 'usersAuthenticators'sourceKey: 'name'targetKey: 'id'
  • usersAuthenticators集合显式定义了uuid(必填,该认证方式下的用户唯一标识)、nicknameavatar、JSON 类型的metauserId/authenticator两个关联键由上述belongsToMany隐式生成。

通常情况下,扩展登录方式用usersusersAuthenticators来存储相应的用户数据即可,特殊情况下才需要自己新增 Collection。

usersAuthenticators的主要字段为

字段说明
uuid该种认证方式的用户唯一标识,如手机号、微信 openid 等
metaJSON 字段,其他需要保存的信息
userId用户 ID
authenticator认证器名字(唯一标识)

对于用户查询和创建操作,authenticators的数据模型AuthModel也封装了几个方法,可以在CustomAuth类中通过this.authenticator[方法名]使用。完整 API 参考 AuthModel。

import { AuthModel } from '@nocobase/plugin-auth'; class CustomAuth extends BaseAuth { async validate() { // ... const authenticator = this.authenticator as AuthModel; this.authenticator.findUser(); // 查询用户 this.authenticator.newUser(); // 创建新用户 this.authenticator.findOrCreateUser(); // 查询或创建新用户 // ... } }

AuthModel的实现见 authenticator.ts:

  • findUser(uuid):通过getUsers关联按uuid命中,返回第一个用户。
  • newUser(uuid, userValues?):在事务内createUser(默认nickname = uuid),并在同一事务中建立through: { uuid }usersAuthenticators关联,随后派发users.afterCreateWithAssociations事件。
  • findOrCreateUser(uuid, userValues?):先findUser,未命中则newUser

这保证了「按第三方唯一标识查找/创建用户」这一扩展认证最常见操作是原子且一致的。

服务端:认证类型注册

扩展的认证方式需要向认证管理模块注册。

class CustomAuthPlugin extends Plugin { async load() { this.app.authManager.registerTypes('custom-auth-type', { auth: CustomAuth, }); } }

AuthManager.registerTypes(authType, authConfig)见 auth-manager.ts。从源码结构看,authConfig的完整结构为:

type AuthConfig = { auth: AuthExtend<Auth>; // 认证类 title?: string; // 认证类型展示名,会出现在后台认证器类型列表 hidden?: boolean; // 是否在认证器类型列表中隐藏 getPublicOptions?: (options) => Record<string, any>; // 计算可公开下发的配置 };

即除必选的auth外,还可提供title/hidden/getPublicOptions。注册后即可通过listTypes()在后台认证器列表中展示。认证器实例的创建(createAuth)会依据authType取回auth构造函数,并把authenticator.options作为构造入参之一,因此后台配置的options会透传给认证类。

客户端:UI 组件注册

客户端用户界面通过用户认证插件客户端提供的接口registerType进行注册:

import AuthPlugin from '@nocobase/plugin-auth/client'; class CustomAuthPlugin extends Plugin { async load() { const auth = this.app.pm.get(AuthPlugin); auth.registerType('custom-auth-type', { components: { SignInForm, // 登录表单 SignInButton, // 登录(第三方)按钮,可以和登录表单二选一 SignUpForm, // 注册表单 AdminSettingsForm, // 后台管理表单 }, }); } }

PluginAuthClient.registerTypeAuthOptions定义见 index.tsx。从源码结构看,AuthOptions.components的每个组件都会接收一个authenticator属性(SignUpForm接收authenticatorName),便于组件读取当前认证器上下文:

export type AuthOptions = { components: Partial<{ SignInForm: ComponentType<{ authenticator: AuthenticatorType }>; SignInButton: ComponentType<{ authenticator: AuthenticatorType }>; SignUpForm: ComponentType<{ authenticatorName: string }>; AdminSettingsForm: ComponentType; }>; };

内核自身的预设认证类型也是通过同一接口注册的——PluginAuthClient.load()registerType(presetAuthType, { components: { SignInForm, SignUpForm, AdminSettingsForm: Options } }),说明「注册类型 + 渲染表单」是统一机制。

登录表单

如果有多个认证器对应的认证类型都注册了登录表单,会以 Tab 的形式展示。Tab 标题为后台配置的认证器标题。

登录按钮

通常为第三方登录按钮,实际上可以是任意组件。

注册表单

如果需要从登录页跳转到注册页,需要在登录组件中自己处理。

后台管理表单

上方为通用的认证器配置,下方为可注册的自定义配置表单部分。

请求接口

在客户端发起用户认证相关的接口请求,可以使用 NocoBase 提供的 SDK。

import { useAPIClient } from '@nocobase/client'; // use in component const api = useAPIClient(); api.auth.signIn(data, authenticator);

详细 API 参考 @nocobase/sdk - Auth。

端到端小结

把上述各部分串起来,一个自定义认证类型的完整落地路径是:

  1. 服务端继承:继承BaseAuth(或Auth),覆写validate()完成身份核验,返回Model用户;登录、发凭证、会话续期、登出失效由基类兜底。
  2. 用户数据:默认复用users+usersAuthenticators;用AuthModel.findUser / newUser / findOrCreateUser完成「第三方唯一标识 → NocoBase 用户」的映射。
  3. 类型注册:在插件load()中调用authManager.registerTypes('custom-auth-type', { auth: CustomAuth }),必要时提供title/hidden/getPublicOptions
  4. 客户端注册:通过auth.registerType('custom-auth-type', { components: { SignInForm / SignInButton / SignUpForm / AdminSettingsForm } })注册 UI。
  5. 请求链路:客户端api.auth.signIn(data, authenticator)→ 请求头X-Authenticator标识认证器 →AuthManager.middleware()解析并创建认证实例 →signIn()调用validate()→ 返回{ user, token },token 进入后续 API 鉴权。

依赖第三方回调的类型,额外增加「获取第三方登录 URL + 注册回调接口 + 回调内主动调用auth.signIn()+ 302 带回 token」的时序即可,其余环节与不依赖回调的类型完全一致。

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 10:39:35

Spring Boot核心注解@SpringBootApplication深度解析

1. SpringBootApplication注解的本质剖析作为Spring Boot项目的启动基石&#xff0c;SpringBootApplication注解远不止表面看到的那么简单。这个复合注解实际上是由三个核心注解组合而成&#xff1a;Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented I…

作者头像 李华
网站建设 2026/9/14 10:38:09

Executive Posture Scorecard: `{project_id}`

Executive Posture Scorecard: {project_id} 【免费下载链接】skills Agent Skills for Google products and technologies 项目地址: https://gitcode.com/GitHub_Trending/skills29/skills MetricStatusDetailsOverall Health Posture{status_badge}{posture_grade}In…

作者头像 李华
网站建设 2026/9/14 10:32:37

绿色证书与综合能源系统优化调度模型解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 10:28:42

LlamaIndex文档处理与知识检索框架实战指南

1. LlamaIndex核心功能解析LlamaIndex是一个专注于文档处理与知识检索的开源框架&#xff0c;其核心价值在于将非结构化文档转化为可被大语言模型高效利用的知识库。我在实际项目中用它处理过技术手册、财务报告等复杂文档&#xff0c;最直观的感受是它解决了传统OCR工具对表格…

作者头像 李华
网站建设 2026/9/14 10:25:55

OpenSandbox 实战:在沙箱内启动 OpenClaw Gateway 并暴露 HTTP 端点

OpenSandbox 实战&#xff1a;在沙箱内启动 OpenClaw Gateway 并暴露 HTTP 端点 【免费下载链接】OpenSandbox Secure, Fast, and Extensible Sandbox runtime for AI agents. 项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox 本指南以 OpenSandbox 官方…

作者头像 李华