跳到主要内容

简单登录

本示例提供了一个分步指南,介绍如何使用 DID Connect 实现一个基本的用户登录系统。其目标是使用用户的 DID 钱包对用户进行身份验证,并检索其姓名和电子邮件地址等基本个人资料信息。这是该库最常见的用例之一。

我们将使用 WalletHandlers 与 Express.js 服务器集成,并向用户请求一个 profile 声明。

工作原理

登录过程遵循标准的 DID Connect 工作流程:

  1. 初始化

    后端使用应用程序的身份设置一个 WalletAuthenticator,并使用一个 WalletHandlers 实例来管理会话。

  2. 附加处理程序

    将一个特定的处理程序附加到 Express 路由(例如 /api/did/login)上。此处理程序定义了要请求的信息(声明)以及在成功验证后执行的逻辑(onAuth)。

  3. 用户交互

    前端显示一个 DID Connect 按钮或二维码,与后端启动会话。

  4. 钱包批准

    用户使用其 DID 钱包扫描二维码,审查请求(分享其个人资料),并批准该请求。

  5. 后端回调

    服务器上的 onAuth 回调被触发,接收用户的 DID(userDid)及其个人资料数据。

  6. 会话创建

    应用程序现在可以使用这些信息来创建用户会话、颁发令牌或将用户的个人资料保存到数据库中。

实现

以下是如何构建一个简单的登录端点。

步骤 1:初始化 Authenticator 和 Handlers

首先,你需要使用你的应用程序详细信息来配置 WalletAuthenticator,并配置 WalletHandlers 来管理会话状态。

简单登录设置

javascript
const express = require('express');
const { fromRandom } = require('@ocap/wallet');
const { WalletAuthenticator, WalletHandlers } = require('@arcblock/did-connect-js');
const SimpleStorage = require('@arcblock/did-connect-storage-nedb');

// 1. 为应用程序创建一个钱包
const wallet = fromRandom();

// 2. 使用应用程序和链信息配置 authenticator
const authenticator = new WalletAuthenticator({
  wallet,
  baseUrl: 'http://localhost:3000', // 你的应用程序的基础 URL
  appInfo: {
    name: 'Simple Login Example',
    description: '一个演示 DID Connect 登录的简单示例',
    icon: '/images/logo.png', // 你的应用程序图标的 URL
  },
  chainInfo: {
    host: 'https://beta.abtnetwork.io/api',
    id: 'beta',
  },
});

// 3. 使用 authenticator 和存储适配器初始化 handlers
const handlers = new WalletHandlers({
  authenticator,
  tokenStorage: new SimpleStorage({ dbPath: '/tmp/did_connect_login_example.db' }),
});

// 4. 创建一个 Express 应用程序
const app = express();

// 如果你的应用程序位于代理之后,这是动态推断 baseUrl 所必需的
app.set('trust proxy', true);
  • WalletAuthenticator:此对象持有你的应用程序的身份(钱包)和元数据(appInfochainInfo),这些信息将显示在用户的钱包中。
  • WalletHandlers:此类负责协调 DID Connect 会话。它需要一个 authenticator 和一个 tokenStorage 适配器来持久化会话状态。did-connect-storage-nedb 是一个简单的基于文件的存储,适合用作示例。

步骤 2:附加登录处理程序

接下来,使用 handlers.attach() 方法创建 API 端点并为你的登录流程定义逻辑。此方法会自动为你创建诸如 /api/did/login/token/api/did/login/status 之类的路由。

附加登录处理程序

javascript
handlers.attach(app, {
  // DID Connect 端点的基本路径
  // 例如,/api/did/login、/api/did/profile
  action: 'login',

  // 定义要从用户钱包请求的声明
  claims: {
    profile: () => ({
      fields: ['fullName', 'email'],
      description: '请提供你的姓名和电子邮件以进行登录。',
    }),
  },

  // 成功验证后执行的回调函数
  onAuth: async ({ userDid, claims }) => {
    // userDid:已验证用户的 DID。
    // claims:用户提交的声明数组。
    try {
      const profile = claims.find((x) => x.type === 'profile');
      console.log('登录成功!', { userDid, profile });

      // 在实际应用中,你通常会:
      // 1. 使用 userDid 在数据库中查找或创建一个用户。
      // 2. 存储个人资料信息。
      // 3. 为用户创建一个会话或颁发一个 JWT。

    } catch (err) {
      console.error('onAuth 回调出错', err);
    }
  },
});

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`服务器正在 http://localhost:${PORT} 上运行`);
  console.log(`DID Connect 登录端点已在 /api/did/login 准备就绪`);
});
  • action: 'login':这将生成的端点的基本路径设置为 /api/did/login
  • claims.profile:此对象指定我们正在请求一个 profile 声明。fields 数组列出了我们需要的具体信息片段,而 description 会在用户的钱包中显示,以解释为什么需要这些信息。
  • onAuth:这是最关键的部分。此函数仅在用户成功验证并批准请求后运行。它接收 userDidclaims 数据。在这里,我们只是简单地记录信息,但在实际应用中,这里就是你处理用户会话管理的地方。

运行此服务器后,你可以使用 DID Connect UX 库集成前端,将其指向 /api/did/login 端点以启动登录流程。

后续步骤

现在你已经有了一个基本的登录系统,可以探索更多高级功能: