Logto 短信通道接入实战:SMSAero 短信服务连接器配置与源码解析

发布时间:2026/9/14 2:14:18
Logto 短信通道接入实战:SMSAero 短信服务连接器配置与源码解析 Logto 短信通道接入实战SMSAero 短信服务连接器配置与源码解析【免费下载链接】logto‍ Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logtoSMSAeroSMS Aero是 Logto 官方支持的短信服务提供商之一本指南以其连接器 packages/connectors/connector-smsaero/README.md 为骨架完整讲解从注册账号、获取 API 凭证到在 Logto 管理控制台编写连接器 JSON、配置验证码短信模板的完整流程并结合 packages/connectors/connector-smsaero/src/index.ts、types.ts 与测试用例深入剖析其发送链路与配置校验机制。读完本文你将能够独立完成 SMSAero 短信通道在 Logto 中的接入、测试与排错。连接器概览SMSAero 连接器是 Logto 官方实现的短信验证码通道SMS connector用于在登录、注册、找回密码、组织邀请、MFA 二次验证等场景下发送验证码短信。其核心实现位于 packages/connectors/connector-smsaero/src/index.ts主要职责包括暴露给 Logto 核心的SmsConnector接口声明metadata、configGuard与sendMessage三个关键成员见 index.ts依据当前用户流程的usageType从已配置的模板列表中挑选匹配的短信模板将模板中的{{code}}占位符替换为实际验证码并携带 Basic Auth 凭证调用 SMSAero 短信发送 API。连接器以logto/connector-smsaero为包名发布依赖logto/connector-kit、gotHTTP 客户端与zod配置校验详见 package.json。第一步注册 SMSAero 账号如果还没有 SMSAero 账号需要先在 SMSAero 官网创建一个新账号已拥有账号可直接跳过。注册完成后建议先通过短信群发控制台确认账户处于可发送状态再回到 Logto 侧配置。第二步获取账号凭证API Key连接器调用 SMSAero 开放 API 时需要一组账号凭证由「账号邮箱 API Key」构成。获取方式如下登录 SMSAero 后台进入「API and SMPP」设置页面在 API 设置区域复制已有的 API-key或点击生成新的 API Key保存好该 Key后续需要与账号邮箱一起填入 Logto 连接器配置。从源码看这组凭证在每次发送时都会被编码为 HTTP Basic Auth 请求头。见 index.tsconst auth Buffer.from(${email}:${apiKey}).toString(base64); return await got.post(endpoint, { headers: { Authorization: Basic ${auth}, }, json: parameters, });也就是说Logto 并不会把明文凭证直接传给 SMSAero而是以email:apiKey的 Base64 形式作为Authorization: Basic ...头随请求发出凭证本身仅保存在 Logto 的连接器配置中。第三步编写连接器 JSON 配置在 Logto 管理控制台的「连接器」页面新建短信连接器并选择 SMSAero 后需要填写email、apiKey、senderName与templates四个字段。README 给出的字段类型如下表名称类型emailstringapiKeystringsenderNamestringtemplatesTemplates[]其中templates数组中的每个模板又包含两个属性模板属性类型可选值contentstringN/A自由文本usageTypeenum stringRegister|SignIn|ForgotPassword|Generic关键字段说明email注册 SMSAero 时使用的账号邮箱。源码中的 zod 校验器要求其必须符合邮箱格式z.string().email()填错会在保存时直接被拒绝见 types.ts。apiKey上一步获取的 API Key任意非空字符串即可通过校验。senderName短信签名发送者名称。README 明确建议可以直接填SMSAero使用 SMSAero 提供的默认签名避免额外申请签名也可以填自定义签名需 SMSAero 侧已完成签名审核。templates短信模板数组。每个模板由usageType用途类型与content短信正文组成。正文中必须保留{{code}}占位符它会在发送时被替换为随机验证码。模板的 usageType 与完整用户流程README 强调要启用完整的用户流程必须同时提供Register、SignIn、ForgotPassword和Generic四种 usageType 的模板。这一点并非建议而是硬性约束——连接器配置校验器smsAeroConfigGuard通过 zod 的refine强制检查这四种模板是否齐全缺失任何一个都会在保存配置时抛出类似Template with UsageType (Register) should be provided!的错误见 types.ts。四种 usageType 的典型用途usageType触发场景Register新用户注册时发送验证码SignIn用户使用验证码登录时ForgotPassword用户重置密码时Generic通用验证码场景作为兜底模板官方默认模板参考虽然 README 只要求四类模板但连接器元数据中实际预置了更完整的默认模板集合defaultValue覆盖了 Logto 支持的九种验证码场景可在 constant.ts 中查看。除上述四类外还包括OrganizationInvitation组织邀请码UserPermissionValidation敏感操作前的权限校验码BindNewIdentifier为已有账号绑定新标识时MfaVerificationMFA 验证码BindMfa绑定 MFA 时的两步验证设置码。这些 usageType 与 Logto 核心的TemplateType枚举一一对应完整枚举定义见 packages/toolkit/connector-kit/src/types/passwordless.ts。如果某个用户流程缺少对应模板发送时会抛出TemplateNotFound错误。配置示例一个可直接使用的完整 JSON 配置如下请将邮箱、Key 与正文替换为自己的内容{ email: your-accountsmsaero.ru, apiKey: your-api-key, senderName: SMSAero, templates: [ { usageType: SignIn, content: Your Logto sign-in verification code is {{code}}. The code will remain active for 10 minutes. }, { usageType: Register, content: Your Logto sign-up verification code is {{code}}. The code will remain active for 10 minutes. }, { usageType: ForgotPassword, content: Your Logto password change verification code is {{code}}. The code will remain active for 10 minutes. }, { usageType: Generic, content: Your Logto verification code is {{code}}. The code will remain active for 10 minutes. } ] }需要说明的是{{code}}的替换并非 SMSAero 连接器独有的逻辑而是复用logto/connector-kit提供的replaceSendMessageHandlebars公共函数它以/{{\s*([\w.])\s*}}/g正则扫描模板将 payload 中存在的变量替换为实际值并支持application.name这类点路径取值见 packages/toolkit/connector-kit/src/index.ts。因此模板正文中除{{code}}外还可以按需引用 payload 中的其他字段。第四步测试 SMSAero 连接器在管理控制台编辑连接器配置时页面底部会提供「发送测试短信」区域输入一个真实的手机号点击 Send即可在点击 Save and Done 之前验证整条链路是否打通。从源码看测试发送走的是与线上完全相同的代码路径——sendMessage函数接收{ to, type, payload }其中type即 usageType如Genericpayload中携带code。发送前会依次执行若调用方未显式传入配置则通过getConfig读取该连接器已保存的配置见 index.ts用smsAeroConfigGuard校验配置合法性按usageType查找对应模板找不到则抛TemplateNotFound组装请求体{ number: to, sign: senderName, text: 替换占位符后的正文 }见 index.tsPOST 到发送端点https://gate.smsaero.ru/v2/sms/send见 constant.ts。发送失败的两种错误形态HTTP 层错误当 SMSAero 返回非 2xx 状态码时连接器会把响应体原文包装为ConnectorError(ConnectorErrorCodes.General, rawBody)抛出方便在 Logto 日志中直接看到服务商侧返回的原因见 index.ts模板缺失当前用户流程在模板列表中找不到对应usageType时抛出TemplateNotFound错误。这两类行为均有对应的单元测试覆盖见 index.test.ts测试通过nock拦截 HTTP 请求分别验证了「正常发送成功」「携带自定义配置发送」「缺失模板报错」「HTTP 400 响应报错」等场景。其中正常发送用例还断言了请求体与 Basic Auth 头的内容可作为排查配置是否正确生效的参照。第五步在登录体验中启用短信登录连接器保存成功并通过测试后还需在 Logto 的登录体验Sign-in Experience设置中把短信验证码注册/登录方式启用用户才能在登录页真正使用手机号 验证码登录。这一步是短信通道真正对最终用户生效的最后一环涉及登录方式、短信验证码的开关配置请参照 Logto 官方文档中关于启用短信登录的说明完成。常见问题与排查思路保存配置时报Template with UsageType (...) should be provided!说明templates缺少Register/SignIn/ForgotPassword/Generic四类中的某一种补齐后重新保存即可。发送测试时报TemplateNotFound测试所用 usageType 对应的模板未配置。若只是发送Generic测试短信确保存在 usageType 为Generic的模板。短信发不出但无明确报错核对email/apiKey是否正确、senderName是否通过 SMSAero 侧审核、手机号是否为国家码格式如13800138000。响应体报错信息晦涩连接器会将 SMSAero API 的原始响应体透传可在 Logto 审计日志中查看General错误的data.message字段通常包含服务商侧的具体原因。小结本文以 connector-smsaero/README.md 为主线完成了 SMSAero 短信通道从「注册账号 → 获取 API Key → 编写连接器 JSON → 测试发送 → 启用短信登录」的完整接入闭环并结合 index.ts 的发送链路、types.ts 的强制模板校验以及 index.test.ts 的测试用例说明了其 Basic Auth 鉴权方式、{{code}}占位符替换机制与错误处理策略。SMSAero 连接器的全部实现细节、默认模板与测试代码均可继续在上述仓库路径中深入研读。【免费下载链接】logto‍ Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考