关于 meteor-accounts
用于配置 Meteor 账户功能的技能,涵盖密码、OAuth、无密码登录、双重验证、令牌存储和邮件流程。它帮助 Meteor 开发者选择账户包,并处理相关配置与安全事项。
主要功能
- 01密码与账户创建流程
- 02OAuth 提供方配置
- 03无密码登录令牌
- 04TOTP 双重验证
- 05HttpOnly Cookie 令牌存储
- 06邮件验证与密码重置
适用场景
- 01为 Meteor 应用选择认证包
- 02添加 Google 等提供方登录
- 03将恢复令牌迁移到 HttpOnly Cookie
- 04实现无密码或 TOTP 登录
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ meteor/ agent-skills --skill meteor-accounts安装后在 Claude Code 中输入/meteor-accounts确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/eval-cases.mdhttp-only-cookies.mdoauth-services.mdpassword-flows.mdpasswordless-requests.mdusers-collection.md详细介绍
Meteor 账户
accounts-base 加上一个风格包(accounts-password、
accounts-google 等)。Meteor 将用户存储在 Meteor.users 中,并向
客户端发送一个映射到该文档的恢复令牌。
决策流程
- 用户名 + 密码?添加
accounts-password。 - 社交登录?添加
accounts-base和提供商包(例如accounts-google),并配置该服务。 - 魔法链接?添加
accounts-passwordless。 - 双重身份验证?在
accounts-password之上添加accounts-2fa。 - 在客户端存储令牌?默认使用 Web Storage。Meteor 3.3+ 支持 HttpOnly Cookie 流程;请参阅下文。
对于自定义用户集合,请在应用读取数据或运行验证器之前配置两个运行时。3.6 RC 修复了集合设置和发布查找问题;更改个人资料规则前,请查看 集合标识与客户端写入策略。
用户名 + 密码
// server/accounts.js
import { Accounts } from "meteor/accounts-base";
import { Meteor } from "meteor/meteor";
Meteor.startup(() => {
Accounts.config({
sendVerificationEmail: true,
});
Accounts.emailTemplates.siteName = "My App";
Accounts.emailTemplates.from = "[email protected]";
});
必须提供 from 地址;在 Meteor 3.5+ 中,省略该地址会导致服务器记录警告。
如果客户端注册表单调用 Accounts.createUser 或 Accounts.createUserAsync,请勿将 forbidClientAccountCreation: true 设为 true。服务器会以 403 Signups forbidden 拒绝该请求。对于仅限邀请或由管理员创建账户的场景,请在客户端和服务器端都设置该选项,移除公开注册界面,并且仅在可信服务器代码完成自身授权检查后调用 Accounts.createUserAsync。
// client/signin.js (Meteor 3.5+)
import { Meteor } from "meteor/meteor";
import { Accounts } from "meteor/accounts-base";
async function signUp({ email, password }) {
await Accounts.createUserAsync({ email, password });
}
async function signIn({ email, password }) {
await Meteor.loginWithPasswordAsync(email, password);
}
客户端仍支持 Accounts.createUser(options, callback)。
Meteor.loginWithPasswordAsync 在 Meteor 3.5 中新增;在较旧的 3.x 版本中,请使用 Meteor.loginWithPassword 的回调形式,或将其封装为 Promise。
在服务器上使用 await Accounts.createUserAsync(options) 和
await Accounts.setPasswordAsync(userId, newPassword)。
HttpOnly Cookie(Meteor 3.3+)
默认令牌存储方式为 Web Storage。要将恢复令牌移入 HttpOnly Cookie,并仅在客户端标签页的内存中保留凭据:
// server
Meteor.startup(() => {
Accounts.config({
clientStorage: "none",
useHttpOnlyCookies: true,
});
});
// settings.json (public; surfaces the same flags to the client)
{
"public": {
"packages": {
"accounts": {
"clientStorage": "none",
"useHttpOnlyCookies": true
}
}
}
}
重启并登录后,Meteor.loginToken* 不再出现在
localStorage 中;浏览器会收到一个 HttpOnly 的 meteor_login_token
Cookie。每个标签页都会在自身内存中保留凭据。DDP 身份验证仍会将恢复令牌读入内存;这无法防止已在应用源站运行的恶意脚本访问该令牌。
使用 [email protected](Meteor 3.5.2)时,只有在服务器端也启用后,服务器才会处理 Cookie 端点。因此,仅在客户端设置可能导致后续处理程序返回 HTML 响应或 404。/set 请求正文大小上限为 4096 字节;更大的请求会返回 HTTP 413。有关路由、版本界限和诊断检查,请参阅
Cookie 端点故障排查。Meteor 3.6-beta.1 的
[email protected] 还要求可信源和有效令牌,使用 SameSite=Strict,并新增单独的按地址端点速率限制。升级前请检查自定义调用方和跨站进入流程。RC 使用
[email protected];重试或丢弃凭据前,请区分无效会话与瞬时错误或速率限制响应。
OAuth(Google 示例)
// server/oauth.js
import { ServiceConfiguration } from "meteor/service-configuration";
await ServiceConfiguration.configurations.upsertAsync(
{ service: "google" },
{
$set: {
clientId: process.env.GOOGLE_CLIENT_ID,
secret: process.env.GOOGLE_CLIENT_SECRET,
loginStyle: "popup",
},
},
);
// client
Meteor.loginWithGoogle(
{ requestPermissions: ["email", "profile"] },
(err) => { if (err) console.error(err); },
);
对于移动设备或没有 window.close / window.opener 的环境,使用
loginStyle: "redirect"。每个提供商都有自己的
accounts-<service> 包:accounts-google、accounts-github、
accounts-facebook、accounts-twitter、accounts-apple、
accounts-meetup、accounts-weibo。
要加密静态存储的 OAuth 密钥,请添加 oauth-encryption,并将
oauthSecretKey 传给 Accounts.config。这会封装
ServiceConfiguration.configurations.secret 中的提供商应用密钥,以及受支持的提供商专属用户令牌字段。它不会创建通用的
Meteor.users.services.<provider>.secret 字段。请参阅 meteor-security。
电子邮件验证与密码重置
// client
Accounts.forgotPassword({ email }, (err) => { ... });
// reset page
Accounts.resetPassword(token, newPassword, (err) => { ... });
// verify email
Accounts.verifyEmail(token, (err) => { ... });
自定义邮件中链接指向的 URL 模式:
Accounts.urls.resetPassword = (token) =>
Meteor.absoluteUrl(`reset/${token}`);
Accounts.urls.verifyEmail = (token) =>
Meteor.absoluteUrl(`verify/${token}`);
两个 setter 也都接受异步函数(Meteor 3.x)。
自定义消息:
Accounts.emailTemplates.resetPassword.subject = () => "Reset your password";
Accounts.emailTemplates.resetPassword.text = (user, url) =>
`Reset link: ${url}`;
无密码登录
添加 accounts-passwordless。请求一次性验证码或链接,然后使用相同的选择器提交验证码:
Accounts.requestLoginTokenForUser(
{
selector: { email },
userData: { email },
options: { userCreationDisabled: false },
},
(error) => { if (error) console.error(error); },
);
Meteor.passwordlessLoginWithToken(
{ email },
token,
(error) => { if (error) console.error(error); },
);
对于仅登录流程,将 userCreationDisabled: true 设为启用。请在服务器端配置 tokenSequenceLength、loginTokenExpirationHours 和 Accounts.emailTemplates.sendLoginToken 模板。将令牌请求方法视为易受滥用的端点,并对重复请求进行速率限制。使用 Meteor 3.6-beta.1 的 [email protected] 和 [email protected] 时,会先验证完整请求,再进行查找/创建,并使用默认的 Accounts DDP 速率限制规则。关于自定义调用方和较早版本的软件包,请参阅无密码请求边界。RC 版本组合为 [email protected] 和 [email protected];请保留默认速率限制器,并处理回调错误,避免立即进入重试循环。
双重身份验证
accounts-2fa 添加了 TOTP。登录流程如下:
- 在 Meteor 3.5+ 中,客户端调用
Meteor.loginWithPasswordAsync(user, password);在较早的 3.x 版本中,调用Meteor.loginWithPassword的回调形式。 - 服务器以
error.error === 'no-2fa-code'拒绝请求。 - 客户端提示用户输入验证码,然后使用
Meteor.loginWithPasswordAnd2faCode(user, password, code, cb)重试。
反面模式
- 将 OAuth 密钥存储在
Meteor.settings.public中。客户端可以看到public。请将密钥放在settings.json的顶层。 - 自行构建密码哈希。
accounts-password使用 bcrypt;请信任它。 - 使用接收密码的方法绕过
forbidClientAccountCreation。风险相同。 - 在延迟执行路径中运行
Accounts.config({ ... })。请在顶层或Meteor.startup中调用它。
另请参阅
references/password-flows.mdreferences/oauth-services.mdreferences/eval-cases.md- 有关 OAuth 密钥加密和 CSP,请参阅
meteor-security技能。