跳转至

批量迁移

批量迁移策略允许您使用用户导入 API一次性将所有用户数据迁移到 Authany。如果您想立即停用旧的身份验证系统并开始使用 Authany,批量迁移是理想的选择。

导入用户后,您需要实现一个使用 Authany 用户会话来保护资源的中间件和服务器端逻辑。因此,所有用户都会被登出,并需要通过 Authany 的身份验证流程重新登录。

本指南将介绍如何使用批量迁移策略,把用户数据从旧的身份验证服务商迁移到 Authany。

何时使用批量迁移

以下是一种可以使用批量迁移策略将用户数据迁移到 Authany 的场景。

  • 当您准备好一次性停用旧的身份验证系统并迁移到 Authany 时。此时,您可以在旧系统中禁用注册,导出用户数据,然后按照完整的批量迁移步骤进行操作。

优点

  • 批量迁移是最直接的方式。
  • 它可以让您一次性迁移所有用户,并尽快停用旧系统。

缺点

  • 从旧系统迁移到 Authany 期间需要一定的停机时间。

步骤 1:从旧系统导出用户数据

从您要迁移出的旧身份验证系统中导出所有用户数据。

以下示例展示了某应用 users 表中的数据行。

| Email              | Email Verified | Name      | Given Name | Family Name | Password Type | Password Hash                                                        |
|--------------------|----------------|-----------|------------|-------------|---------------|----------------------------------------------------------------------|
| user1@example.com  | true           |           |            |             | bcrypt        | $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy         |
| user2@example.com  | false          | John Doe  | John       | Doe         | bcrypt        | $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy         |

您可以从任何身份验证系统(包括您自己搭建的系统)导出用户,然后将数据重新格式化,以匹配 Authany 用户导入 API 的数据结构。

步骤 2:将用户数据重新格式化为支持的 JSON 格式

将导出的用户数据重新格式化为符合用户导入 API 数据结构的 JSON 文档。

然后即可使用这份重新格式化的 JSON 文档,通过导入 API 导入您的用户数据。

下面是前面 users 表示例重新格式化后的结果:

[
  {
    "email": "user1@example.com",
    "email_verified": true,
    "password": {
      "type": "bcrypt",
      "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
    }
  },
  {
    "email": "user2@example.com",
    "email_verified": false,
    "name": "John Doe",
    "given_name": "John",
    "family_name": "Doe",
    "password": {
      "type": "bcrypt",
      "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
    }
  }
]

步骤 3:导入格式化后的用户数据

通过向用户导入 API 的 _api/admin/users/import 端点发送 POST HTTPS 请求,导入您格式化好的用户数据。

const data = {
  identifier: "email",
  records: [
    {
      email: "user1@example.com",
      email_verified: true,
      password: {
        type: "bcrypt",
        password_hash:
          "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy",
      },
    },
    {
      email: "user2@example.com",
      email_verified: false,
      name: "John Doe",
      given_name: "John",
      family_name: "Doe",
      password: {
        type: "bcrypt",
        password_hash:
          "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy",
      },
    },
  ],
};

const options = {
  method: "POST",
  headers: {
    "Content-type": "application/json",
    Authorization: "Bearer <ADMIN_API_JWT>",
  },
  body: JSON.stringify(data),
};

const appUrl = "<YOUR_AUTHGEAR_ENDPOINT>";

fetch(`${appUrl}/_api/admin/users/import`, options)
  .then((result) => result.json())
  .then((result) => console.log(JSON.stringify(result)));

上面的 JavaScript 代码使用用户导入 API 导入了示例 users 表中的数据。该 API 需要一个有效的 Admin API JWT 进行身份验证。

了解更多关于使用用户导入 API 的信息,请点击这里。

步骤 4:在中间件和服务器端逻辑中使用 Authany 会话

现在您已经成功将用户导入 Authany,可以开始使用 Authany 会话来保护应用中的页面了。

为此,需要实现一个使用 Authany 会话的中间件和服务器端逻辑。

说明

注意: 部署使用 Authany 会话的中间件和服务器端逻辑后,所有用户都会被登出,并需要通过 Authany 的身份验证流程重新登录。

以下是一个简单 Express.js 应用的示例,其中包含一个使用 Authany 会话的中间件:

const express = require("express");
const axios = require("axios");
const node_jwt = require("jsonwebtoken");
const jwksClient = require("jwks-rsa");

const app = express();
const port = 3000;

const appUrl = "https://authui.mycompany.com";
const getJwksUri = async (appUrl) => {
  const config_endpoint = appUrl + "/.well-known/openid-configuration";
  const data = await axios.get(config_endpoint);
  return data.data.jwks_uri;
};

const authenticateToken = async (req, res, next) => {
  const requestHeader = req.headers;
  if (requestHeader.authorization == undefined) {
    return res.sendStatus(401);
  }
  const authorizationHeader = requestHeader.authorization.split(" ");
  const access_token = authorizationHeader[1];

  const decoded_access_token = node_jwt.decode(access_token, {
    complete: true,
  });
  if (decoded_access_token == null) {
    return res.sendStatus(401)
  }
  const jwks_uri = await getJwksUri(appUrl);
  const client = jwksClient({
    strictSsl: true,
    jwksUri: jwks_uri,
  });
  const signing_key = await client.getSigningKey(
    decoded_access_token.header.kid
  );

  try {
    const verify = node_jwt.verify(access_token, signing_key.publicKey, {
      algorithms: ["RS256"],
    });
    console.log(JSON.stringify(verify));
  } catch (error) {
    return res.sendStatus(403);
  }

  next();
};

app.get("/", (req, res) => {
  res.send(
    "Hello world, this is an unprotected page, a good place to start an authentication flow."
  );
});

app.get("/protected", authenticateToken, (req, res) => {
  res.json({ message: "This is a protected route" });
});

app.listen(port, () => {
  console.log(`server started on port ${port}`);
});

这个示例应用使用 “Bearer <access token>” 保护 /protected 路由。您可以点击这里了解更多关于在后端验证访问令牌和使用 Authany 的内容。

步骤 5:使用 Authany 对用户进行身份验证

更新您的应用,让用户可以通过 Authany 的身份验证流程重新登录。

您可以使用以下平台对应的任意 SDK,将 Authany 无缝集成到您的应用中:

或者手动将 Authany 添加为 OAuth 2.0 提供方。

完成!现在,您的用户可以登录您的应用,并使用与旧身份验证服务商相同的用户账号。