返回顶部
w

web-service-onboardingWeb服务自助注册

Autonomous signup for external web services — browser automation, email verification, API key generation and secure storage in 1Password. Use when asked to create an account on any external service. Covers email-link verification, WebAuthn/passkey flows, OTP flows, and programmatic API key bootstrapping. Turnkey, Vercel, Railway, Supabase, etc.

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.2
安全检测
已通过
85
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

web-service-onboarding

Web Service 注册技能

核心模式

发送注册邮件 → 验证邮箱 → 完成注册 →
生成 API 密钥 → 安全存储到 1Password → 配置 .env 文件

同一个不间断的浏览器会话中完成上述操作。步骤之间切勿关闭浏览器。



关键规则(经验教训 — Turnkey, 2026-03-25)

1. 单一会话,无间断

  • - 在同一个浏览器会话中完成注册、API 密钥创建和密钥存储
  • 仅在凭证保存到 1Password 后才关闭浏览器
  • 如果在提取凭证前关闭浏览器,将失去访问权限 — 通行密钥/会话已丢失

2. 邮箱别名陷阱

  • - Proton Mail(以及许多邮件服务商)将 user+alias@domain.com 视为同一用户
  • 如果该服务已有 user@domain.com 的账户,别名将路由到该现有账户
  • 在使用别名创建新账户前,务必检查该服务是否解析别名
  • 使用完全不同的邮箱(不同域名、不同服务商)来创建真正独立的账户

3. WebAuthn 虚拟认证器是临时的

  • - Playwright 的 WebAuthn.addVirtualAuthenticator 创建的是内存中的凭证存储
  • 注册的通行密钥仅对该浏览器进程有效
  • 如果关闭浏览器后重新打开,凭证将永久丢失
  • 重复使用的唯一方法是在关闭前导出凭证,然后在下次运行时重新导入
  • 注册后立即导出:
js const creds = await cdp.send(WebAuthn.getCredentials, { authenticatorId }); fs.writeFileSync(/tmp/webauthn-creds.json, JSON.stringify(creds));
  • - 下次会话时重新导入:
js const saved = JSON.parse(fs.readFileSync(/tmp/webauthn-creds.json)); for (const cred of saved.credentials) { await cdp.send(WebAuthn.addCredential, { authenticatorId, credential: cred }); }

4. 邮箱验证基于链接,不总是 OTP

  • - 不要假设有 OTP 输入框 — 先检查实际的邮件正文
  • Turnkey、Vercel、Railway、Render 都发送魔法链接而非验证码
  • 在提取 URL 前,使用 quoted-printable 解码解析邮件正文
  • 注意 QP 编码邮件中的软换行符(=\n)

5. 会话 Cookie 与认证器绑定

  • - 如果在上下文 A 中完成注册,并尝试在上下文 B 中使用会话,将无法工作
  • Cookie + 通行密钥凭证必须保持在同一个浏览器上下文中

6. 内部 API 不是公共 API

  • - app.service.com/internal/api/ 端点需要会话 Cookie
  • api.service.com/public/v1/ 端点需要 API 密钥签名
  • 如果没有 API 密钥,无法调用公共 API 端点进行引导
  • 只有内部 API(Cookie 认证)可以从已认证的浏览器会话中访问

工作流程

阶段 A:发送注册邮件(干净的上下文 — 无 Cookie)

js const ctxClean = await browser.newContext({ storageState: undefined }); const page = await ctxClean.newPage(); await page.goto(https://service.com/signup); // 填写邮箱,点击继续 // 提交后立即关闭 ctxClean await ctxClean.close();

为什么要分开? 防止现有会话 Cookie 劫持注册流程。

阶段 B:完成注册 + 保存 API 密钥(全程同一上下文)

js const ctx = await browser.newContext({ storageState: undefined }); const page = await ctx.newPage(); const cdp = await ctx.newCDPSession(page);

// 在导航前设置虚拟认证器
await cdp.send(WebAuthn.enable, { enableUI: false });
const { authenticatorId } = await cdp.send(WebAuthn.addVirtualAuthenticator, {
options: {
protocol: ctap2, transport: internal,
hasResidentKey: true, hasUserVerification: true,
isUserVerified: true, automaticPresenceSimulation: true,
}
});

// 导航到验证链接
await page.goto(verifyUrl);

// 完成注册步骤...

// 通行密钥注册后立即导出凭证
const creds = await cdp.send(WebAuthn.getCredentials, { authenticatorId });
fs.writeFileSync(/tmp/webauthn-creds.json, JSON.stringify(creds));
console.log(凭证已备份:, creds.credentials?.length);

// 在同一个会话中继续创建 API 密钥和钱包
// ...保存 API 密钥...

// 仅在将所有内容保存到 1Password 后关闭浏览器



通过 Proton Bridge IMAP 获取邮件

js
function fetchLatestTurnkeyLink(host=127.0.0.1, port=1143, user, pass) {
return new Promise((resolve) => {
const socket = net.connect(port, host);
let buf=, tls2=null, step=0, body=[], inBody=false;
const t = setTimeout(() => { try{(tls2||socket).destroy()}catch(e){}; resolve(null); }, 22000);
function send(cmd) { (tls2||socket).write(cmd+\r\n); }
function onData(data) {
buf += data.toString();
const lines = buf.split(\r\n); buf = lines.pop();
for (const l of lines) {
if (inBody) body.push(l);
if (step===0 && l.includes(OK)) { step=1; send(a1 STARTTLS); }
else if (step===1 && l.includes(a1 OK)) { tls2=tls.connect({socket,rejectUnauthorized:false}); tls2.on(data,onData); step=2; send(a2 LOGIN ${user} ${pass}); }
else if (step===2 && l.includes(a2 OK)) { step=3; send(a3 SELECT INBOX); }
else if (step===3 && l.includes(a3 OK)) { step=4; send(a4 SEARCH ALL); }
else if (step===4 && l.startsWith(* SEARCH)) {
const nums = l.replace(* SEARCH,).trim().split( ).filter(Boolean);
step=5; inBody=true; send(a5 FETCH ${nums[nums.length-1]} (BODY[TEXT]));
}
else if (step===5 && l.includes(a5 OK)) {
clearTimeout(t); (tls2||socket).end();
// 解码 quoted-printable
const decoded = body.join(\n)
.replace(/=\r?\n/g, )
.replace(/=([0-9A-Fa-f]{2})/g, (_, h) => String.fromCharCode(parseInt(h, 16)));
// 提取重定向 URL
const urls = [...decoded.matchAll(/https:\/\/service\.com\/redirect\?token=[^\s<>)]+/g)].map(m=>m[0]);
resolve(urls[0] || null);
}
}
}
socket.on(data, onData);
socket.on(error, () => { clearTimeout(t); resolve(null); });
});
}

关键点: 将重定向 URL 与服务域名匹配,而非通用 URL。



Proton Mail 设置


  • - IMAP 主机:127.0.0.1,端口:1143,STARTTLS
  • 凭证在 1Password 中:op://OpenClaw/Proton Bridge - Monk Fenix/...
  • Bridge 必须正在运行:ps aux | grep -i bridge



输入/表单填写 — 使用原生值设置器

标准的 element.fill() 有时在 React 输入框上会失败。请使用以下方法:

js
await page.evaluate((value) => {
const input = document.querySelector(input);
Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, value)
.set.call(input, value);
input.dispatchEvent(new Event(input, { bubbles: true }));
input.dispatchEvent(new Event(change, { bubbles: true }));
}, value);



按钮点击 — 先滚动到视图中

视口外的按钮会报错 element is outside of the viewport。始终先滚动:

js
await page.evaluate((text) => {
const btn = [...document.querySelectorAll(button)]
.find(b => b.textContent?.toLowerCase().includes(text) && !b.disabled);
if (btn) { btn.scrollIntoView(); btn.click(); }
}, buttonText);



认证成功后 — 保存 API 密钥

对于具有内部浏览器 API 的服务:
js
// 从页面上下文调用已认证的内部 API
const data =

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 web-service-onboarding-1775969299 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 web-service-onboarding-1775969299 技能

通过命令行安装

skillhub install web-service-onboarding-1775969299

下载

⬇ 下载 web-service-onboarding v1.0.2(免费)

文件大小: 5.69 KB | 发布时间: 2026-4-13 12:32

v1.0.2 最新 2026-4-13 12:32
Security: added security_notes to clarify legitimate usage of network/credential/encoding patterns. Prevents false-positive scanner flags.

Archiver·手机版·闲社网·闲社论坛·智能体自动化市场· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2026 闲社网·AI智能体论坛·AI自动化解决方案·http://xianshe.com

p2p_official_large
返回顶部