@yeying-community/web3-bs 1.0.16 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,476 @@
1
+ # 快速上手
2
+
3
+ 本文档按 3 条接入路线来组织:
4
+
5
+ 1. 钱包插件路线
6
+ 2. App 钱包路线
7
+ 3. 中心化服务路线
8
+
9
+ 目标不是罗列全部 API,而是让 DApp 团队先判断“我该走哪条路”,再落到对应的代码组合。
10
+
11
+ ## 1. 安装
12
+
13
+ ```bash
14
+ npm install @yeying-community/web3-bs
15
+ ```
16
+
17
+ ## 2. 先选路线
18
+
19
+ ### 2.1 钱包插件路线
20
+
21
+ 适合:
22
+ - PC Web 为主
23
+ - 浏览器里已有钱包插件
24
+ - 需要标准连接、签名、SIWE 登录
25
+ - 若需要 UCAN 多后端授权,优先走钱包 UCAN RPC;不支持时 SDK 会回退本地 Ed25519 session
26
+
27
+ ### 2.2 App 钱包路线
28
+
29
+ 适合:
30
+ - 移动端 Web
31
+ - 没有浏览器插件,但可以连接钱包 App
32
+ - 钱包 App 或适配层能暴露 EIP-1193 能力
33
+
34
+ ### 2.3 中心化服务路线
35
+
36
+ 适合:
37
+ - 无钱包、无插件,或者不要求链上身份
38
+ - 希望统一用中心化会话、JWT 或中心化 UCAN
39
+ - 目标是降低移动端接入成本
40
+
41
+ ## 3. 路线一:钱包插件
42
+
43
+ 这是当前最完整、最自然的路线。
44
+
45
+ ### 3.1 前提
46
+
47
+ - 浏览器内有可用插件钱包
48
+ - 至少支持 EIP-1193
49
+ - 若要走 UCAN,多后端授权链路要求可完成 SIWE 签名(Root),session 签名优先用钱包 UCAN RPC:
50
+ - `yeying_ucan_session`(可选,优先)
51
+ - `yeying_ucan_sign`(可选,优先)
52
+ - 若 RPC 不可用,`web3-bs` 自动回退本地 Ed25519 session key(浏览器端 IndexedDB 持久化)
53
+
54
+ ### 3.2 典型流程图
55
+
56
+ ```text
57
+ Detect Provider -> Request Accounts -> Sign / Login -> Access API -> Access WebDAV
58
+ ```
59
+
60
+ ### 3.3 适用钱包
61
+
62
+ - YeYing:支持标准连接 + 钱包托管 UCAN session/sign
63
+ - MetaMask 等 EIP-1193 钱包:支持连接、签名、challenge/SIWE 登录;UCAN session/sign 可走 SDK 本地回退
64
+
65
+ 关键边界:
66
+ - “支持插件钱包”不等于“所有插件都支持 UCAN”
67
+ - 通用插件至少可走标准签名 / JWT 登录
68
+ - UCAN 路径优先使用钱包 UCAN RPC,不支持时可走 SDK 本地 session 回退
69
+
70
+ ### 3.4 最短接入:只做连接与签名
71
+
72
+ ```ts
73
+ import { getProvider, requestAccounts, signMessage } from '@yeying-community/web3-bs';
74
+
75
+ const provider = await getProvider({ preferYeYing: true });
76
+ if (!provider) throw new Error('No injected wallet provider');
77
+
78
+ const accounts = await requestAccounts({ provider });
79
+ const address = accounts[0];
80
+ if (!address) throw new Error('No account available');
81
+
82
+ const signature = await signMessage({
83
+ provider,
84
+ address,
85
+ message: 'hello web3-bs',
86
+ });
87
+ ```
88
+
89
+ 需要用户名或邮箱时,应在账户连接后按字段申请钱包资料权限:
90
+
91
+ ```ts
92
+ import { connectAndGetWalletProfile } from '@yeying-community/web3-bs';
93
+
94
+ const profile = await connectAndGetWalletProfile({
95
+ provider,
96
+ fields: ['username', 'email'],
97
+ });
98
+
99
+ console.log(profile.address, profile.profile);
100
+ ```
101
+
102
+ 完整授权生命周期、错误处理与隐私要求见[钱包资料授权](./钱包资料授权.md)。
103
+
104
+ 推荐用途:
105
+ - 登录前置连接
106
+ - 简单签名授权
107
+ - 账户选择与账户变更监听
108
+
109
+ ### 3.5 插件钱包常规路线:challenge / SIWE 登录 + JWT
110
+
111
+ 这条路适用于所有标准 EIP-1193 钱包。
112
+
113
+ ```ts
114
+ import {
115
+ loginWithChallenge,
116
+ authFetch,
117
+ refreshAccessToken,
118
+ } from '@yeying-community/web3-bs';
119
+
120
+ const login = await loginWithChallenge({
121
+ baseUrl: 'https://api.example.com/api/v1/public/auth',
122
+ });
123
+
124
+ const profileRes = await authFetch(
125
+ 'https://api.example.com/api/v1/public/profile',
126
+ { method: 'GET' },
127
+ { baseUrl: 'https://api.example.com/api/v1/public/auth' }
128
+ );
129
+
130
+ const refreshed = await refreshAccessToken({
131
+ baseUrl: 'https://api.example.com/api/v1/public/auth',
132
+ });
133
+ ```
134
+
135
+ 这条路线下,SDK 负责维护:
136
+ - access token 缓存
137
+ - refresh 流程
138
+ - `authFetch` 的统一请求行为
139
+
140
+ ### 3.6 UCAN 路线:一次授权多个后端
141
+
142
+ 这条路优先使用钱包 UCAN RPC;若钱包不支持,SDK 会自动回退本地 UCAN session。
143
+
144
+ ```ts
145
+ import {
146
+ createDelegationUcan,
147
+ createUcanSession,
148
+ getOrCreateUcanRoot,
149
+ createInvocationUcan,
150
+ authUcanFetch,
151
+ deriveAppIdFromLocation,
152
+ } from '@yeying-community/web3-bs';
153
+
154
+ const provider = await getProvider({ preferYeYing: true });
155
+ if (!provider) throw new Error('No injected wallet provider');
156
+
157
+ const appId = deriveAppIdFromLocation(window.location) || 'localhost-8001';
158
+ const scope = `app:all:${appId}`;
159
+
160
+ const session = await createUcanSession({ provider });
161
+
162
+ const root = await getOrCreateUcanRoot({
163
+ provider,
164
+ session,
165
+ capabilities: [{ with: scope, can: 'invoke' }],
166
+ });
167
+
168
+ const delegateSession = await createUcanSession({ provider, id: 'demo-delegate' });
169
+ const delegation = await createDelegationUcan({
170
+ issuer: session,
171
+ audience: delegateSession.did,
172
+ capabilities: [{ with: scope, can: 'invoke' }],
173
+ proofs: [root],
174
+ });
175
+
176
+ const ucan = await createInvocationUcan({
177
+ issuer: delegateSession,
178
+ audience: 'did:web:api.example.com',
179
+ capabilities: [{ with: scope, can: 'invoke' }],
180
+ proofs: [delegation],
181
+ });
182
+
183
+ const res = await authUcanFetch(
184
+ 'https://api.example.com/api/v1/public/profile',
185
+ { method: 'GET' },
186
+ { ucan }
187
+ );
188
+ ```
189
+
190
+ 这条路线下,SDK 负责维护:
191
+ - UCAN session 读取与创建
192
+ - Root proof 复用
193
+ - Delegation / Invocation 证明链组装
194
+ - Invocation token 缓存
195
+ - 面向多个后端的 audience/capability 组装
196
+
197
+ ### 3.7 插件钱包下的 WebDAV
198
+
199
+ #### 用 JWT 或 UCAN token 直接访问
200
+
201
+ ```ts
202
+ import { createWebDavClient, deriveAppIdFromLocation } from '@yeying-community/web3-bs';
203
+
204
+ const appId = deriveAppIdFromLocation(window.location) || 'localhost-8001';
205
+
206
+ const client = createWebDavClient({
207
+ baseUrl: 'https://webdav.example.com',
208
+ prefix: '/dav',
209
+ token: '<JWT_OR_UCAN>',
210
+ });
211
+
212
+ await client.upload(`/apps/${appId}/hello.txt`, 'Hello WebDAV');
213
+ ```
214
+
215
+ #### 用 UCAN 自动初始化存储
216
+
217
+ ```ts
218
+ import { initWebDavStorage, deriveAppIdFromLocation } from '@yeying-community/web3-bs';
219
+
220
+ const appId = deriveAppIdFromLocation(window.location) || 'localhost-8001';
221
+
222
+ const storage = await initWebDavStorage({
223
+ baseUrl: 'https://webdav.example.com',
224
+ prefix: '/dav',
225
+ audience: 'did:web:webdav.example.com',
226
+ appId,
227
+ capabilities: [{ with: `app:all:${appId}`, can: 'write' }],
228
+ });
229
+
230
+ await storage.client.upload(`${storage.appDir}/hello.txt`, 'Hello WebDAV');
231
+ ```
232
+
233
+ 更详细的有效期说明见 [UCAN有效期与续期机制](./UCAN有效期与续期机制.md)。
234
+
235
+ #### 创建长期分享链接(warehouse)
236
+
237
+ ```ts
238
+ const share = await storage.client.createShareLink({
239
+ path: `${storage.appDir}/hello.txt`,
240
+ // 0 表示不过期(长期分享)
241
+ expiresValue: 0,
242
+ expiresUnit: 'day',
243
+ });
244
+
245
+ console.log('share url =', share.url);
246
+ ```
247
+
248
+ WebDAV 注意:
249
+ - `baseUrl` 只填根地址
250
+ - 子路径通过 `prefix` 指定
251
+ - capability 推荐使用 `with/can`,资源格式统一为 `app:<scope>:<appId>`(常用 `app:all:<appId>`)
252
+ - 在 warehouse 的 UCAN 授权链路中,`createShareLink` / `listShareLinks` 仅允许操作 `app` scope 授权目录内的文件
253
+ - 若走 JWT 或未携带 UCAN `app` scope,请以服务端策略为准,目录隔离不会自动生效
254
+ - 本地调试建议使用 `deriveAppIdFromLocation(window.location)`,会把 `127.0.0.1` / `::1` 统一映射为 `localhost`,避免同端口生成两套应用目录
255
+
256
+ ## 4. 路线二:App 钱包
257
+
258
+ 这条路线的关键不是“是不是手机 App”,而是:
259
+
260
+ > 能不能把钱包能力适配成前端可调用的 Provider
261
+
262
+ ### 4.1 前提
263
+
264
+ - 钱包 App 自身提供浏览器内 Provider
265
+ - 或通过桥接层 / SDK 暴露 EIP-1193 接口
266
+
267
+ 如果没有 EIP-1193 或等价适配层,`web3-bs` 不能直接接。
268
+
269
+ ### 4.2 典型流程图
270
+
271
+ ```text
272
+ Connect App Wallet -> Get Provider Adapter -> Request Accounts -> Sign / Login -> Access API
273
+ ```
274
+
275
+ ### 4.3 推荐路线
276
+
277
+ #### 4.3.1 App 钱包只支持标准 EIP-1193
278
+
279
+ 这是最常见情况。
280
+
281
+ 建议走:
282
+ - `getProvider` / 适配后的 `provider`
283
+ - `requestAccounts`
284
+ - `signMessage`
285
+ - `loginWithChallenge`
286
+ - `authFetch`
287
+ - `createWebDavClient`
288
+
289
+ 示例:
290
+
291
+ ```ts
292
+ import {
293
+ requestAccounts,
294
+ loginWithChallenge,
295
+ authFetch,
296
+ } from '@yeying-community/web3-bs';
297
+
298
+ const provider = appWalletProvider;
299
+ const accounts = await requestAccounts({ provider });
300
+ const address = accounts[0];
301
+ if (!address) throw new Error('No account available');
302
+
303
+ await loginWithChallenge({
304
+ provider,
305
+ address,
306
+ baseUrl: 'https://api.example.com/api/v1/public/auth',
307
+ });
308
+
309
+ const res = await authFetch(
310
+ 'https://api.example.com/api/v1/public/profile',
311
+ { method: 'GET' },
312
+ { baseUrl: 'https://api.example.com/api/v1/public/auth' }
313
+ );
314
+ ```
315
+
316
+ #### 4.3.2 App 钱包的 UCAN 路径
317
+
318
+ 这种情况可以直接复用“钱包插件路线”的 UCAN 路径。
319
+
320
+ 也就是说:
321
+ - Provider 入口不同
322
+ - `web3-bs` 的 UCAN 调用方式不变(钱包 UCAN RPC 优先,不可用时本地回退)
323
+
324
+ ### 4.4 App 钱包路线的关键限制
325
+
326
+ - `web3-bs` 不自带 WalletConnect 或 App Bridge 实现
327
+ - 它假设你已经拿到了可调用的 `provider`
328
+ - 如果 App 钱包支持 EIP-1193 签名,UCAN 路线通常可用;是否使用钱包托管 UCAN session 取决于是否实现 UCAN RPC
329
+
330
+ ### 4.5 App 钱包下的 WebDAV
331
+
332
+ 推荐优先走:
333
+ - challenge/SIWE 登录 -> JWT
334
+ - `createWebDavClient` 访问 WebDAV
335
+
336
+ 若 App 钱包可完成签名,就可以走:
337
+ - `initWebDavStorage`
338
+
339
+ ## 5. 路线三:中心化服务
340
+
341
+ 这条路线适合“无钱包插件、无 App 钱包、或业务不强依赖链上身份”的场景。
342
+
343
+ ### 5.1 典型流程图
344
+
345
+ ```text
346
+ Create Session / Login -> Get Token -> Access API -> Access WebDAV
347
+ ```
348
+
349
+ ### 5.2 中心化 JWT 路线
350
+
351
+ 如果中心化服务给你的是 JWT,而不是 UCAN,推荐直接用:
352
+ - `setAccessToken`
353
+ - `authFetch`
354
+ - `createWebDavClient`
355
+
356
+ ```ts
357
+ import {
358
+ setAccessToken,
359
+ authFetch,
360
+ createWebDavClient,
361
+ deriveAppIdFromLocation,
362
+ } from '@yeying-community/web3-bs';
363
+
364
+ const token = '<ACCESS_TOKEN>';
365
+ setAccessToken(token, { storeToken: true });
366
+
367
+ const profileRes = await authFetch(
368
+ 'https://api.example.com/api/v1/public/profile',
369
+ { method: 'GET' }
370
+ );
371
+
372
+ const appId = deriveAppIdFromLocation(window.location) || 'localhost-8001';
373
+ const webdav = createWebDavClient({
374
+ baseUrl: 'https://webdav.example.com',
375
+ prefix: '/dav',
376
+ token,
377
+ });
378
+ await webdav.upload(`/apps/${appId}/hello.txt`, 'Hello');
379
+ ```
380
+
381
+ ### 5.3 中心化 UCAN 路线
382
+
383
+ 如果中心化服务会先发 session,再签发 UCAN,可以用:
384
+ - `createCentralSession`
385
+ - `issueCentralUcan`
386
+ - `authCentralUcanFetch`
387
+
388
+ ```ts
389
+ import {
390
+ createCentralSession,
391
+ issueCentralUcan,
392
+ authCentralUcanFetch,
393
+ } from '@yeying-community/web3-bs';
394
+
395
+ const session = await createCentralSession({
396
+ baseUrl: 'https://api.example.com/api/v1/public/auth/central',
397
+ subject: 'mobile-user-001',
398
+ });
399
+
400
+ const issued = await issueCentralUcan({
401
+ baseUrl: 'https://api.example.com/api/v1/public/auth/central',
402
+ sessionToken: session.sessionToken,
403
+ audience: 'did:web:api.example.com',
404
+ capabilities: [{ with: 'app:all:mobile-demo', can: 'read' }],
405
+ });
406
+
407
+ const res = await authCentralUcanFetch(
408
+ 'https://api.example.com/api/v1/public/profile/me',
409
+ { method: 'GET' },
410
+ {
411
+ ucan: issued.ucan,
412
+ baseUrl: 'https://api.example.com/api/v1/public/auth/central',
413
+ }
414
+ );
415
+ ```
416
+
417
+ 这条路线下,SDK 负责维护:
418
+ - central session token 缓存
419
+ - UCAN issue 请求封装
420
+ - central UCAN 请求发送
421
+
422
+ ### 5.4 中心化服务路线的边界
423
+
424
+ - 它不等价于钱包本地 UCAN
425
+ - 它更适合移动端无插件场景
426
+ - 如果你只需要登录后端与访问 WebDAV,JWT 路线通常比中心化 UCAN 更简单
427
+
428
+ ## 6. 三条路线如何选
429
+
430
+ - 你有浏览器插件钱包:优先“钱包插件路线”
431
+ - 你有钱包 App + Provider 适配层:走“App 钱包路线”
432
+ - 你没有钱包能力,或业务接受中心化身份:走“中心化服务路线”
433
+
434
+ 更细一点:
435
+ - 只要连接、签名、登录:任意 EIP-1193 钱包即可
436
+ - 要走 UCAN 多后端授权:优先钱包 UCAN RPC;不支持时使用 SDK 本地 session 回退
437
+ - 要覆盖移动端无插件:优先中心化服务路线
438
+
439
+ ## 6.5 加密 / 解密(命名安全套件)
440
+
441
+ DApp 端用独立于钱包密码的"数据密码"对任意数据进行加解密,密文走 `v1:<suite>:...` 格式可粘贴存储。详见 [加解密服务.md](./加解密服务.md)。
442
+
443
+ ```ts
444
+ import { encrypt, decrypt, getSupportedCipherSuites } from '@yeying-community/web3-bs';
445
+
446
+ const suites = await getSupportedCipherSuites();
447
+ // → ['aes-256-gcm', 'sm4-cbc-hmac-sm3', 'sha-256', 'sm3']
448
+
449
+ const ciphertext = await encrypt({
450
+ data: '夜莺钱包敏感数据 🔐',
451
+ password: 'app-specific-passphrase-2024',
452
+ suite: 'aes-256-gcm'
453
+ });
454
+ // → v1:aes-256-gcm:<salt>:<iv>:<ciphertext>
455
+
456
+ const plaintext = new TextDecoder().decode(
457
+ await decrypt({ ciphertext, password: 'app-specific-passphrase-2024' })
458
+ );
459
+ // → 夜莺钱包敏感数据 🔐
460
+ ```
461
+
462
+ **前提**:站点已 `requestAccounts` 授权 + 钱包已解锁。静默执行,无审批弹窗。
463
+
464
+ ## 7. 最常见的 API 组合
465
+
466
+ - 插件钱包 + JWT 登录:`getProvider` + `requestAccounts` + `loginWithChallenge` + `authFetch`
467
+ - 插件钱包 + UCAN:`createUcanSession` + `getOrCreateUcanRoot` + `createInvocationUcan`
468
+ - 插件钱包 + 加解密:`getProvider` + `requestAccounts` + `encrypt` / `decrypt`(静默,需先解锁)
469
+ - App 钱包 + JWT 登录:`requestAccounts` + `loginWithChallenge` + `authFetch`
470
+ - 中心化 JWT:`setAccessToken` + `authFetch` + `createWebDavClient`
471
+ - 中心化 UCAN:`createCentralSession` + `issueCentralUcan` + `authCentralUcanFetch`
472
+
473
+ ## 8. 进一步阅读
474
+
475
+ - [SDK能力](./SDK能力.md)
476
+ - [移动端认证与授权选型指南](./移动端认证与授权选型指南.md)
@@ -0,0 +1,54 @@
1
+ # 文档导航
2
+
3
+ 这套文档平铺在 `docs/` 目录,按“快速接入 -> 综合能力 -> 有效期机制 -> 移动端补充 -> 评审与契约”组织。
4
+
5
+ ## 文档分工
6
+
7
+ | 文档 | 主要读者 | 主要回答的问题 | 不重点覆盖 |
8
+ | --- | --- | --- | --- |
9
+ | [快速上手](./快速上手.md) | DApp 前端工程师 | 如何在浏览器里快速接入 SIWE/UCAN/WebDAV | 方案定位与组织边界 |
10
+ | [SDK能力](./SDK能力.md) | 前端负责人、架构师、联调工程师 | 库定位、能力矩阵、账户管理、登录授权与 API 组合 | 逐页面操作指南 |
11
+ | [UCAN有效期与续期机制](./UCAN有效期与续期机制.md) | DApp 前端工程师、后端联调工程师 | UCAN token 有效期配置、skew 判断、过期刷新重试与错误分类 | 后端 UCAN 校验实现 |
12
+ | [加解密服务](./加解密服务.md) | DApp 前端工程师、架构师 | 命名安全套件、encrypt/decrypt/getSupportedCipherSuites 用法、安全模型 | 私钥/助记词保护(那是钱包职责) |
13
+ | [钱包资料授权](./钱包资料授权.md) | DApp 前端工程师、产品安全负责人 | 如何按字段授权并读取钱包用户名和邮箱 | 邮箱真实性验证与业务账号体系 |
14
+ | [移动端认证与授权选型指南](./移动端认证与授权选型指南.md) | 移动端方案设计者 | 无插件场景如何做身份与授权路径选择 | PC 插件细节 |
15
+ | [开放接口规范](./开放接口规范.yaml) | 前后端接口定义维护者 | 标准接口契约 | 业务方案背景 |
16
+
17
+ ## 推荐阅读顺序
18
+
19
+ 1. [快速上手](./快速上手.md)
20
+ 2. [SDK能力](./SDK能力.md)
21
+ 3. [加解密服务](./加解密服务.md)
22
+ 4. [钱包资料授权](./钱包资料授权.md)
23
+ 5. [UCAN有效期与续期机制](./UCAN有效期与续期机制.md)
24
+ 6. [移动端认证与授权选型指南](./移动端认证与授权选型指南.md)
25
+ 7. [开放接口规范](./开放接口规范.yaml)
26
+
27
+ ## 按人群阅读
28
+
29
+ ### DApp 前端工程师
30
+
31
+ - 首先看 [快速上手](./快速上手.md)
32
+ - 路线与能力看 [SDK能力](./SDK能力.md)
33
+ - 长请求、流式请求和 token 过期处理看 [UCAN有效期与续期机制](./UCAN有效期与续期机制.md)
34
+ - 移动端补充看 [移动端认证与授权选型指南](./移动端认证与授权选型指南.md)
35
+ - 加密/解密 DApp 敏感数据看 [加解密服务](./加解密服务.md)
36
+
37
+ ### 钱包 / 后端联调工程师
38
+
39
+ - 协议流程、边界与 API 细节看 [SDK能力](./SDK能力.md)
40
+ - token 有效期、错误分类和续期策略看 [UCAN有效期与续期机制](./UCAN有效期与续期机制.md)
41
+ - 接口契约看 [开放接口规范](./开放接口规范.yaml)
42
+
43
+ ### 架构与方案设计者
44
+
45
+ - 能力边界与路线取舍先看 [SDK能力](./SDK能力.md)
46
+ - 授权有效期与长请求体验风险看 [UCAN有效期与续期机制](./UCAN有效期与续期机制.md)
47
+ - 移动端特殊路径看 [移动端认证与授权选型指南](./移动端认证与授权选型指南.md)
48
+ - 接口标准看 [开放接口规范](./开放接口规范.yaml)
49
+
50
+ ## 维护原则
51
+
52
+ - `docs/` 目录保持平铺,不再分层级子目录。
53
+ - 一个文档聚焦一个核心问题,交叉引用而不是重复展开。
54
+ - 文档名与标题保持一致,避免“文件名是 A、内容其实是 B”。
@@ -0,0 +1,151 @@
1
+ # 移动端认证与授权选型指南
2
+
3
+ 本文档用于在“移动端没有浏览器钱包插件”的前提下,统一评估认证与授权路径。
4
+ 目标是让你先做路线决策,再落到 `web3-bs` 的 API 组合。
5
+
6
+ ## 1. 快速对比
7
+
8
+ | 路径 | 身份来源 | UCAN 形态 | 接入复杂度 | 推荐场景 |
9
+ | --- | --- | --- | --- | --- |
10
+ | 钱包 App 连接(WalletConnect / Deep Link) | 链上钱包 | 可支持(依赖钱包能力) | 中 | 需要尽量保留钱包体验与链上身份 |
11
+ | 嵌入式钱包(托管 / MPC) | 钱包 SDK | 可支持(依赖 SDK) | 中-高 | 移动端无插件且可接受钱包 SDK 成本 |
12
+ | SSO / WebAuthn(JWT) | 中心化身份 | 不使用 UCAN | 中 | 登录体验优先、业务不强依赖链上身份 |
13
+ | 中心化 UCAN 发行 | 中心化身份 + Issuer 服务 | 支持(中心化信任) | 高 | 需要 UCAN 令牌形态并接受中心化信任 |
14
+ | PC 首次绑定 + 移动端长期会话 | PC 钱包 + 后端长期会话 | 通常移动端侧不直接用钱包 UCAN | 中-高 | 允许 PC 首次认证,移动端长期免钱包 |
15
+ | 传统账号(手机号/邮箱+2FA) | 中心化账号 | 不使用 UCAN | 低 | 最快上线、实现成本最低 |
16
+
17
+ ## 2. 决策顺序
18
+
19
+ 1. 是否必须保留链上身份来源?
20
+ 2. 是否可接受用户安装钱包 App 或接入钱包 SDK?
21
+ 3. 是否接受中心化身份体系(SSO / WebAuthn / 账号密码)?
22
+ 4. 是否必须保留 UCAN 令牌形态?
23
+ 5. 是否允许“PC 首次绑定、移动端长期会话”作为折中方案?
24
+
25
+ ## 3. 路径详解
26
+
27
+ ### 3.1 钱包 App 连接(WalletConnect / Deep Link)
28
+
29
+ 适用:
30
+ - 用户愿意安装钱包 App
31
+ - 业务希望保留链上身份
32
+ - 希望移动端体验接近 PC 钱包插件
33
+
34
+ 核心前提:
35
+ - 移动端可拿到 EIP-1193 provider
36
+ - 若要完整 UCAN 流程,钱包需支持 `yeying_ucan_session` / `yeying_ucan_sign`
37
+
38
+ `web3-bs` 推荐组合:
39
+ - 登录:`requestAccounts` + `loginWithChallenge` + `authFetch`
40
+ - UCAN:`createUcanSession` + `getOrCreateUcanRoot` + `createInvocationUcan`
41
+ - WebDAV:`initWebDavStorage` 或 `createWebDavClient`
42
+
43
+ ### 3.2 嵌入式钱包(托管 / MPC)
44
+
45
+ 适用:
46
+ - 不希望用户额外安装插件
47
+ - 可以接受钱包 SDK、合规和运维成本
48
+
49
+ 核心前提:
50
+ - 嵌入式钱包 SDK 可暴露 EIP-1193 provider
51
+ - 若仅支持 `personal_sign`,则只适合 SIWE/JWT 路线
52
+
53
+ `web3-bs` 推荐组合:
54
+ - 登录:`requestAccounts` + `loginWithChallenge` + `authFetch`
55
+ - UCAN(可选):同 3.1(前提是 SDK 支持钱包 UCAN RPC 或使用本地回退)
56
+ - WebDAV:`createWebDavClient` / `initWebDavStorage`
57
+
58
+ ### 3.3 SSO / WebAuthn(JWT)
59
+
60
+ 适用:
61
+ - 登录成功率和移动端体验优先
62
+ - 不强依赖链上身份语义
63
+
64
+ 核心思路:
65
+ - 认证后端完成 SSO 或 Passkey 验证并签发 JWT
66
+ - DApp 使用 JWT 调用多后端
67
+
68
+ `web3-bs` 推荐组合:
69
+ - `setAccessToken` + `authFetch` + `refreshAccessToken`
70
+ - WebDAV 使用 `createWebDavClient`(Bearer JWT)
71
+
72
+ 备注:
73
+ - 该路径不依赖钱包,不使用钱包 UCAN。
74
+
75
+ ### 3.4 中心化 UCAN 发行
76
+
77
+ 适用:
78
+ - 希望保持 UCAN 令牌形态
79
+ - 接受中心化 Issuer 信任模型
80
+
81
+ 核心思路:
82
+ - 用户先走中心化登录(SSO/WebAuthn/JWT)
83
+ - Issuer 服务签发 UCAN(`iss` 为 Issuer DID)
84
+ - 业务后端信任 Issuer 公钥并校验 `aud` / `cap` / `exp`
85
+
86
+ `web3-bs` 推荐组合:
87
+ - `getCentralIssuerInfo`
88
+ - `createCentralSession`
89
+ - `issueCentralUcan` / `createAndIssueCentralUcan`
90
+ - `authCentralUcanFetch`
91
+
92
+ 边界说明:
93
+ - 这是“中心化 UCAN”,不是“用户钱包控制 UCAN”。
94
+
95
+ ### 3.5 PC 首次绑定 + 移动端长期会话
96
+
97
+ 适用:
98
+ - 用户可在 PC 端完成一次钱包认证
99
+ - 移动端希望后续免钱包、低摩擦访问
100
+
101
+ 核心思路:
102
+ - PC 钱包登录后,后端签发一次性绑定票据
103
+ - 移动端绑定设备并换取长期 JWT/会话
104
+
105
+ `web3-bs` 推荐组合:
106
+ - PC 端:标准钱包登录或 UCAN 流程
107
+ - 移动端:`setAccessToken` + `authFetch` + `createWebDavClient`
108
+
109
+ ### 3.6 传统账号(手机号/邮箱 + 2FA)
110
+
111
+ 适用:
112
+ - 业务不依赖链上身份
113
+ - 优先追求实现效率和稳定性
114
+
115
+ 核心思路:
116
+ - 账号体系签发 JWT
117
+ - 多后端统一校验 JWT
118
+
119
+ `web3-bs` 推荐组合:
120
+ - `setAccessToken` + `authFetch` + `refreshAccessToken`
121
+ - WebDAV:`createWebDavClient`
122
+
123
+ ## 4. 实施建议
124
+
125
+ ### 4.1 先定“身份来源”,再定“令牌形态”
126
+
127
+ - 身份来源:钱包 / SSO / 账号体系
128
+ - 令牌形态:JWT / 钱包 UCAN / 中心化 UCAN
129
+
130
+ 这两个维度分开设计,文档和实现会更清晰。
131
+
132
+ ### 4.2 优先使用统一资源模型
133
+
134
+ 无论 JWT 还是 UCAN,资源权限建议统一到服务端策略,例如:
135
+ - `app:all:<appId>`
136
+ - `app:read:<appId>`
137
+ - `app:write:<appId>`
138
+
139
+ 这样可减少多后端权限映射成本。
140
+
141
+ ### 4.3 明确中心化 UCAN 的信任边界
142
+
143
+ - 钱包 UCAN:用户控制签名能力
144
+ - 中心化 UCAN:Issuer 服务控制签发能力
145
+
146
+ 这两者在安全语义上不同,文档与产品上应明确标注。
147
+
148
+ ## 5. 推荐阅读
149
+
150
+ - [快速上手](./快速上手.md)
151
+ - [SDK能力](./SDK能力.md)