ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Wasp 社交登录默认行为全解析:首次登录自动建号、随机用户名/密码生成与自定义覆盖

Wasp 社交登录默认行为全解析:首次登录自动建号、随机用户名/密码生成与自定义覆盖 Wasp 社交登录默认行为全解析首次登录自动建号、随机用户名/密码生成与自定义覆盖【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp导读本文以 Wasp 0.11.8 版本文档中关于社交登录默认行为_default-behaviour.md为核心完整讲解用户通过 Google、GitHub 等第三方账号首次登录时Wasp 在后台自动完成的建号与账号关联流程以及它对username、password字段的默认填充逻辑。读完本文你将掌握社交登录背后的数据模型要求userEntity与externalAuthEntity、随机用户名的生成机制并能通过getUserFieldsFn与configFn覆盖默认行为实现让用户自己设置用户名等自定义注册流程。社交登录在 Wasp 中的定位在 Wasp 中社交登录Social Login例如 Log in with Google被视为处理用户账号的最佳方案之一。Wasp 的设计目标是让接入社交登录尽可能无痛用户无需在你的应用中重新注册直接使用其在 Google、GitHub 等平台已有的账号即可登录。从 社交登录总览 可知Wasp 内置支持多个社交登录提供商且所有提供商共享同一套通用行为每个提供商账号的接入配置方式一致在app.auth.methods中声明所有提供商共用同一个externalAuthEntity即用户与第三方账号的关联实体首次登录的默认行为完全一致——这正是本文的核心主题。默认行为首次登录时发生了什么根据 默认行为文档当用户第一次通过社交账号登录时Wasp 会自动执行两件事创建新用户账号并将其与所选提供商如 Google、GitHub的账号进行关联用于未来登录。也就是说第二次起用户直接登录即可无需重复注册流程。根据你的userEntity用户实体字段定义自动填充部分默认值userEntity字段默认行为username字段Wasp 会将其设置为一个随机用户名例如nice-blue-horse-14357password字段Wasp 会将其设置为一个随机字符串这是 Wasp 在社交登录场景下对username/password字段的兜底处理目的是让既有的、面向邮箱密码登录的数据模型也能兼容社交登录的用户。文档明确指出这是auth各方法之间历史遗留的耦合Wasp 计划在未来版本中移除这一行为。因此在实际开发中应把这段默认逻辑视为过渡性实现而不是长期依赖的最终方案。需要重点理解的三点首次的定义只有用户从未登录过时才会触发建号后续登录走的是已有关联关系。关联关系是持久化的建号时同时写入SocialLogin关联记录用户与提供商账号一一绑定。默认行为可被覆盖如果默认的随机用户名不符合业务需求可以通过下文的自定义机制接管。支撑默认行为的数据模型userEntity 与 externalAuthEntity要启用社交登录包括触发上述默认行为必须在app.auth中声明两个实体userEntity代表用户的实体是所有auth方法社交或非社交都必需的externalAuthEntity代表用户与社交提供商的关联的实体仅使用依赖外部提供商的auth方法如 Google、GitHub时需要。所有社交提供商共用同一个externalAuthEntity。一个完整的声明如下来自 总览文档app myApp { wasp: { version: ^0.11.0 }, title: My App, auth: { userEntity: User, externalAuthEntity: SocialLogin, methods: { google: {} }, onAuthFailedRedirectTo: /login }, } entity User {psl id Int id default(autoincrement()) //... externalAuthAssociations SocialLogin[] psl} entity SocialLogin {psl id Int id default(autoincrement()) provider String providerId String user User relation(fields: [userId], references: [id], onDelete: Cascade) userId Int createdAt DateTime default(now()) unique([provider, providerId, userId]) psl}SocialLogin即externalAuthEntity各字段含义如下provider提供商名称如google、githubproviderId用户在该提供商平台上的 IDuserId用户在你平台上的 ID引用userEntity的id字段user指向userEntity的关系createdAt关联创建的时间戳unique([provider, providerId, userId])对三者组合的唯一约束防止同一用户与同一提供商重复绑定。而userEntity需要额外声明一个字段externalAuthAssociations指向externalAuthEntity的关系即上面的SocialLogin[]。与默认行为的关系首次登录建号时Wasp 写入的正是这条SocialLogin关联记录providerproviderId唯一确定一个第三方账号userId指向新建的本平台账号。理解这张表就能理解自动建号 账号关联背后的落库逻辑。随机用户名背后的工具函数默认行为中出现的nice-blue-horse-14357这类随机用户名并非凭空生成。根据 用户名生成说明Wasp 在wasp/core/auth.js中暴露了两个可用于生成用户名的函数generateAvailableUsername接收一个字符串数组和一个可选的分隔符生成一个以随机数字结尾、且在数据库中尚未被占用的字符串。例如对 GitHub 用户 Jim Smith可能生成Jim.Smith.3984。generateAvailableDictionaryUsername生成一个随机的词典短语用户名同样保证数据库中不存在重复例如nice-blue-horse-27160。两个函数都会自动检查数据库中是否已被占用Available 的含义避免生成重复用户名。默认行为中的nice-blue-horse-14357正是后者的典型输出。这两个函数同样可以在自定义覆盖逻辑中直接复用见下文。覆盖默认行为getUserFieldsFn 与 configFn默认行为虽然开箱即用但业务上常常需要自定义。Wasp 提供两种覆盖机制来自 覆盖说明getUserFieldsFn控制创建新用户时写入哪些字段例如用提供商返回的displayName填充用户昵称或让用户自定义用户名configFn控制提供商 OAuth 配置Client ID、Client Secret、scope 等。场景一让用户自己设置用户名三步法如果不想使用随机用户名可以让用户自定义用户名。以 Google 为例见 总览文档 的 Overrides 章节分三步第 1 步在User实体上增加isSignupComplete字段用于标识用户是否完成了注册流程entity User {psl id Int id default(autoincrement()) username String? unique isSignupComplete Boolean default(false) externalAuthAssociations SocialLogin[] psl}第 2 步通过getUserFieldsFn覆盖默认行为让新用户创建时isSignupComplete保持falseapp myApp { wasp: { version: ^0.11.0 }, title: My App, auth: { userEntity: User, externalAuthEntity: SocialLogin, methods: { google: { getUserFieldsFn: import { getUserFields } from server/auth/google.js } }, onAuthFailedRedirectTo: /login }, }import { GetUserFieldsFn } from wasp/types export const getUserFields: GetUserFieldsFn async (_context, _args) { return { isSignupComplete: false, } }Wasp 会自动生成GetUserFieldsFn类型帮助你正确为getUserFields函数标注类型见 类型说明。第 3 步在客户端根据状态跳转。用useAuth()钩子见 使用认证总览读取user.isSignupComplete为false时跳转到资料编辑页import useAuth from wasp/auth/useAuth import { Redirect } from react-router-dom export function HomePage() { const { data: user } useAuth() if (user.isSignupComplete false) { return Redirect to/edit-user-details / } // ... }同样的原理也适用于更复杂的注册流程——只需把布尔型的isSignupComplete换成能承载多值的字段如currentSignupStep。场景二使用提供商返回的账号信息当用户通过社交提供商登录时后端会收到该用户在提供商的资料数据。Wasp 允许在getUserFieldsFn中访问这些数据。例如为User实体增加displayName字段并用提供商资料填充来自 GitHub 文档 与 Google 文档app myApp { wasp: { version: ^0.11.0 }, title: My App, auth: { userEntity: User, externalAuthEntity: SocialLogin, methods: { gitHub: { configFn: import { getConfig } from server/auth/github.js, getUserFieldsFn: import { getUserFields } from server/auth/github.js } }, onAuthFailedRedirectTo: /login }, } entity User {psl id Int id default(autoincrement()) username String unique displayName String externalAuthAssociations SocialLogin[] psl}import type { GetUserFieldsFn } from wasp/types import { generateAvailableDictionaryUsername } from wasp/core/auth.js export const getUserFields: GetUserFieldsFn async (_context, args) { const username await generateAvailableDictionaryUsername() const displayName args.profile.displayName return { username, displayName } } export function getConfig() { return { clientID, // look up from env or elsewhere clientSecret, // look up from env or elsewhere scope: [], } }如果你想基于 GitHub 显示名生成更人性化的用户名可以改用generateAvailableUsername并指定分隔符import type { GetUserFieldsFn } from wasp/types import { generateAvailableUsername } from wasp/core/auth.js export const getUserFields: GetUserFieldsFn async (_context, args) { const username await generateAvailableUsername( args.profile.displayName.split( ), { separator: . } ) return { username } }其中context包含User实体args对象包含提供商的 profile 信息你可以随意利用这些数据。注意 Google 与 GitHub 在 scope 上的差异GitHub 示例为scope: []Google 示例通常为scope: [profile, email]——需要哪些权限由各提供商的 OAuth 规范决定。实战落地GitHub / Google 的完整接入流程默认行为只有在社交登录真正启用后才会触发。完整启用一个提供商的步骤如下以 GitHub 为例Google 流程与之对称详见 github.md 与 google.md在main.wasp中启用提供商methods: { gitHub: {} }用google: {}则启用 Google同时声明userEntity与externalAuthEntity定义两个实体User含externalAuthAssociations关系与SocialLogin见上文创建 OAuth 应用在 GitHub / Google 开发者控制台创建 OAuth App授权回调地址在开发环境填http://localhost:3000/auth/login/githubGoogle 为http://localhost:3000/auth/login/google部署后换成线上域名对应路径配置环境变量写入项目根目录的.env.server文件GITHUB_CLIENT_IDyour-github-client-id GITHUB_CLIENT_SECRETyour-github-client-secret # 若启用 Google 则替换为 # GOOGLE_CLIENT_IDyour-google-client-id # GOOGLE_CLIENT_SECRETyour-google-client-secret定义路由与页面route LoginRoute { path: /login, to: LoginPage } page LoginPage { component: import { Login } from client/pages/auth.tsx }创建客户端页面在client/pages/auth.tsx中使用 Wasp 自动生成的 Auth UI 组件见 Auth UI 文档import { LoginForm } from wasp/auth/forms/Login export function Login() { return ( Layout LoginForm / /Layout ) }之后运行wasp db migrate-dev与wasp start即可得到带社交登录功能的可用应用。Auth UI 会自动渲染各提供商的登录按钮如果你需要自定义表单也可以使用更低层的 UI 辅助——从wasp/auth/helpers/Google、wasp/auth/helpers/GitHub导入SignInButton组件或signInUrl链接自行拼装。仓库中的真实示例ask-the-documents在仓库的 ask-the-documents 示例 中可以看到现代版本0.26.0社交登录的实际落地其在app.auth中声明userEntity为User并通过methods.google的userSignupFields新版本对getUserFieldsFn的演进命名与configFn接入 Googleimport { defineUserSignupFields } from wasp/server/auth; export const googleUserSignupFields defineUserSignupFields({ email: (data: any) data.profile.email, }); export function getGoogleAuthConfig() { return { scopes: [profile, email], }; }这个示例直观展示了覆盖默认字段填充的工程化写法用defineUserSignupFields声明新用户创建时从提供商 profile 中提取email并配置scopes。相比 0.11.8 文档中的getUserFieldsFn现代 API 命名与类型辅助更加完善但背后的设计思想默认建号 → 覆盖字段填充 → 自定义 config一脉相承。小结Wasp 社交登录的默认行为可以用一句话概括首次登录自动建号并关联第三方账号username与password字段由 Wasp 兜底填充随机值。理解这一行为后你可以知道nice-blue-horse-14357这类用户名从何而来以及如何用generateAvailableDictionaryUsername/generateAvailableUsername复现同样的可用性校验逻辑通过getUserFieldsFn新版本为userSignupFields与configFn覆盖建号字段与 OAuth 配置结合isSignupComplete标志实现让用户自己取名的多步注册流程。需要留意的是随机填充username/password属于文档明确标注的历史耦合行为官方计划在未来移除因此在设计长期业务逻辑时应优先考虑显式的覆盖方案。【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表