跳转到内容
全部文章
约 4 分钟阅读

SaaS 认证不只是一个登录表单

沿着身份走一遍会话、工作区归属、受保护动作与退出登录——这些是一个漂亮的登录界面证明不了的。

supastack 团队

让一个系统掌管身份

登录表单收集的是一次请求。认证系统决定该请求是否确立身份,并签发应用其余部分信任的会话。把这份职责放在一个地方,可以避免每条路由各自发明对“已登录用户”的解释。

supastack 组合 Better Auth 处理身份与会话。应用代码在受保护边界解析会话,并将其关联到工作区。界面可以展示有用的访问状态,但客户端状态绝不能成为操作已获授权的证据。

这条规则必须在产品发布的每个端面上成立。Web、移动端与桌面端应该消费同一个身份判定,而不是各实现一遍——三种“已登录”的解释正是账户 bug 的来源。

审慎地选择登录方式

每种方式都在用摩擦换取攻击面与外部依赖。密码需要重置流程和速率限制。魔法链接和一次性码依赖邮件的送达能力。OAuth 把身份委托给 Google、GitHub 或 Apple 这类供应商——也继承了它们的宕机、授权页和回调规则。

supastack 通过 Better Auth 把这些方式组合在一个统一的身份判定之后——邮箱 OTP、密码、魔法链接、OAuth,外加可选的双因素与通行密钥。只发布你的用户真正需要的最小集合;每多一种方式,就多一条回调路径、多一种失败模式、多一条发布前要验证的流程。认证指南讲了接线方式。

当一个人可以用多种方式登录时,要决定这些方式如何汇合。解析到同一邮箱地址的 Google 账户和魔法链接应该落在同一个身份上,而不是两个。账户关联规则是身份判定的一部分,搞错了会造出重复用户,几个月后以离奇丢失的数据浮出水面。

会话才是真正要紧的凭证

登录之后,每个请求携带的是会话而不是密码。它的过期、存储与失效规则定义了真实的安全姿态。退出后仍然存活的会话、被移除的工作区成员还能继续使用的会话,都是再精致的登录界面也修补不了的认证失败。

提前定好生命周期:会话活多久、用户能否查看并撤销自己的活跃会话、改密码、改邮箱或被移出工作区对它们有什么影响。套件里会话管理之所以是独立模块,正因为这些决定容易被推迟、补做又很昂贵。

把会话与所请求的记录连起来

登录不等于有权访问所有记录。在服务端解析用户的工作区,并把该范围带入读写。任务标识符或恢复链接是对工作的引用,不是取回它的许可——工作区边界一文详细讲了边界的那一侧。

按固定顺序解析范围:先认证会话,再加载成员关系,然后带着这个工作区上下文去读或写——绝不能反过来。中间件可以重定向匿名访客,但无法为操作授权;检查属于实际碰到记录的服务端 action 或路由 handler。

账户有完整生命周期,而不只是起点

开通是这条边界的第一场考试。用户注册时,随之而来的工作区与归属记录必须能安全地创建不止一次——生命周期钩子可能被供应商、重试或客服工具重放。重复的事件应该是空操作,而不是重复的组织。

生命周期的末端值得同样的用心。改邮箱、重置密码、移除成员、删除账户、导出数据,每个都是带着自己滥用场景的小流程——能用两次的重置链接、泄露队友记录的导出。supastack 正是为此内置了 GDPR 导出与会话管理;无论你基于什么构建,都要给这些平淡无奇的流程留预算。

测试整个生命周期,包括终点

一次成功的登录测试有用但不完整。演练无效凭证、过期或复用的验证码、匿名请求与跨工作区访问。验证退出登录会使会话失效,且回归的客户端不能继续用此前授权的界面执行受保护工作。

区分 handler 测试与部署验收。内存适配器可以确立真实认证 handler 的语义,却不能证明 Postgres 持久化或供应商回调。在声称完整登录流程可用之前,用已部署的依赖验证配置的 origin、回调路径、会话恢复与退出。

  • 无效凭证以及过期或复用的验证码被拒绝。
  • 匿名与跨工作区请求拿不到任何归属数据。
  • 退出登录会使会话失效——过期的客户端无法继续行动。
  • 生命周期钩子重放时,已开通的记录保持幂等。
  • 真实供应商的回调在配置的 origin 上可用——经过验证,而非想当然。

常见认证问题

下面的问题,会在登录表单做完、系统必须持续运转之后浮现。

  • 中间件足以保护路由吗? —— 中间件只是方便的重定向,不是授权层。每个服务端 action 和路由都要自己解析会话与工作区;页面级守卫只是藏起界面,并没有为操作授权。
  • 自己造认证还是用库? —— 会话语义很少是 SaaS 的差异化所在。像 Better Auth 这样有维护的库,放在清晰的模块边界后面,能给你经过测试的原语,同时把要紧的决定——范围、生命周期——留在你的代码里。
  • 会话和工作区是什么关系? —— 会话标识的是人,工作区标识的是他可以触碰的记录。每个请求都在服务端解析成员关系,绝不信任客户端发来的工作区 ID。
  • B2B 客户对认证有什么期待? —— 带角色的团队工作区、OAuth 登录、会话可见性与可撤销性,以及审计轨迹。双因素与通行密钥对管理员角色也越来越是标配。
  • 生产环境里是什么弄坏认证? —— 通常是边缘地带:只存在于本地的回调 URL、开通两次的钩子、比成员关系活得还久的会话。要测流程的末端,而不只是开头。

常见问题

14 个问题

supastack 是什么?

supastack 是用于构建 AI 驱动 SaaS 产品的模块化基础。它把通用基础设施整合在一起,让你专注于产品专属的功能。

它支持 Web 和移动端吗?

支持。supastack 包含 Next.js 与 Expo 应用,作为 Web 与移动端体验的起点。

包含哪些认证方式?

Better Auth 覆盖邮箱/密码、OTP 与社交登录。个人工作区随账户一起开通,产品记录从第一天起就有边界。

AI 是如何支持的?

supastack 包含可配置的多供应商 AI、用量追踪、预算,以及加密的自带密钥(BYOK)支持。

订阅如何处理?

对于基于该套件构建的产品,Stripe 计费、订阅与权限构成付费访问的基础。供应商密钥仅存于服务端。

我的产品专属代码放在哪里?

产品专属功能保留在独立的代码库中,产品通过配置接入 supastack 的基础模块。

supastack 如何定价?

套件为一次性购买、终身更新:单框架 249 美元(限时优惠价,较常规价 349 美元优惠 100 美元),或全框架(Next.js、iOS、Android)499 美元(限时优惠价,较常规价 599 美元优惠 100 美元),每个额外开发者席位 75 美元。套件本身没有订阅。本站结账后通过邮件发送许可证密钥,仓库访问通过 GitHub 邀请授予。

工作区如何界定我的数据?

用户记录按 workspaceId 划定边界。身份、权限、AI 用量、计费事件与审计条目都留在个人工作区边界内。

后台任务如何工作?

Trigger.dev 是明确的任务运行时。JobRunner 契约只承诺 enqueue、status 与 cancel——工作流语义保持 Trigger.dev 专有且显式。

邮件与营销触达有何不同?

事务性邮件覆盖产品工作流,如任务完成通知。冷触达与营销活动属于产品自身的范畴,不在本套件的邮件模块内。

移动端购买如何运作?

移动端已支持 RevenueCat 原生购买和恢复购买,访问权限由服务端验证。发布前需配置商店账户并完成设备测试。Web 计费保持独立。

AI 供应商密钥存放在哪里?

自带密钥凭证经过加密且仅存于服务端。密钥在日志中被脱敏;用量与预算在工作区级别保持可见。

结账支持哪些付款方式?

Stripe 托管结账接受银行卡,在 Stripe 账户启用后还可提供支付宝与微信支付——方便中国买家。钱包授权为异步确认,付款完成后许可证页面会立即更新。

我能申请退款吗?

获得代码仓库访问权限后,supastack 将永久归你所有,因此无法退款。但请放心,你将获得包含终身更新的完整源代码,可为你自己或客户构建并发布无限数量的产品。你只需注意不能转卖代码,也不能将仓库作为启动模板二次分发。

CN