Better Auth 集成

createAuthMiddleware

一个与框架无关的工厂,具备路由过滤、会话计时和生命周期钩子。启动时调用一次,然后在各个请求之间复用。

createAuthMiddleware 用你在每个请求中都需要的内容包装了 identifyUser:路由过滤、会话解析耗时、生命周期钩子,以及静默错误处理。启动时调用一次,然后在你框架的 middleware/hook 系统中使用返回的函数。

server/middleware/auth-identify.ts
import { createAuthMiddleware } from 'evlog/better-auth'

const identify = createAuthMiddleware(auth, {
  exclude: ['/api/auth/**', '/api/public/**'],
  include: ['/api/**'],
  maskEmail: true,
})

函数签名为 (log, headers, path?) => Promise<boolean>。它会解析会话、调用 identifyUser、将耗时记录到 auth.resolvedIn、触发生命周期钩子,并且会静默捕获错误,因此会话解析永远不会中断请求。

选项

继承所有 identifyUser 选项,另外还有:

选项类型默认值描述
excludestring[]['/api/auth/**']要跳过的路由模式(glob)。
includestring[]undefined如果设置,则只会解析匹配的路由。
onIdentify(log, session) => voidundefined成功识别后调用。
onAnonymous(log) => voidundefined未找到会话时调用。

路由过滤

跳过 Better Auth 自身的路由和任何公开端点,以避免无谓的数据库查询:

const identify = createAuthMiddleware(auth, {
  exclude: [
    '/api/auth/**',     // Better Auth 自身
    '/api/public/**',   // 公共端点
    '/api/health',      // 健康检查
  ],
})

对于高流量应用,可以反过来使用这个模型——只在需要会话的路由上解析会话:

const identify = createAuthMiddleware(auth, {
  include: ['/api/dashboard/**', '/api/account/**'],
})

includeexclude 使用 glob 模式(***)。如果你需要更细粒度的控制,可以同时提供两者——exclude 的优先级高于 include

生命周期钩子

使用 onIdentify 在用户被识别后执行操作——例如,通过尾采样强制保留高级用户的日志:

server/middleware/auth-identify.ts
const identify = createAuthMiddleware(auth, {
  onIdentify: (log, session) => {
    if (session.user.plan === 'enterprise') {
      log.set({ _forceKeep: true })
    }
  },
  onAnonymous: (log) => {
    log.set({ anonymous: true })
  },
})

钩子会在会话解析完成且 identifyUser 已设置其字段后触发。它们会在每个通过 include/exclude 过滤器的请求上运行,因此请保持它们足够快且无副作用。

onIdentify 的常见模式:
  • 为管理员或高价值套餐强制保留审计日志。
  • 用从会话中加载的功能标志或租户信息为请求打标签。
  • 为计费目的按用户递增计数器。

错误处理

该中间件会捕获来自 getSession 的每一个错误,并且不记录任何日志——无论认证后端可用与否,你的请求都会继续执行。宽事件中仍然会包含 auth.resolvedInauth.identified: false,因此你可以从仪表盘上监控会话解析健康状况。