Skip to content
Go to Dashboard

迁移用户到 GenAuth

如果你想将自己系统中的用户导入到 GenAuth,请务必阅读此部分的指引。

如果你想以不停机的形式平稳迁移用户到 GenAuth,你需要使用自定义数据库功能,编写相对应的数据库脚本。用户第一次认证时会使用你配置的自定义数据脚本认证用户,认证成功之后会将其迁移到 GenAuth 数据库;用户第二次认证的时候,会使用 GenAuth 数据库进行检验。当所有用户都至少认证一次的时候,代表迁移过程完成。详情请见惰性迁移用户到 GenAuth

如果你希望用自己的数据库存储用户数据,不想把用户数据暴露给 GenAuth,可以完全使用自定义数据库保存用户数据

你也可以选择一次性将用户全部导入到 GenAuth,我们提供了 API & SDK 帮助你快速编写导入脚本,详情请见使用 SDK 导入用户。在此过程中,你还需要先确认一个问题:能否获取到用户的明文密码?如果你能够获取到,直接使用明文密码创建新用户即可;如果不能,你需要先 编写自定义密码函数,这样当用户在 GenAuth 中进行登录的时候,会使用你编写的自定义密码加密、验证函数,用户之前的密码依旧能够生效,不需要要求用户重置自己的密码。

如果你属于内部员工的使用场景(EIAM),还可以从企业微信钉钉LDAP ServerWindows 本地的 Active Directory 等第三方企业身份源导入组织机构和用户目录,详情请见此

使用 SDK 导入用户

GenAuth 同时支持了 Java、JavaScript/Node.js、Python、PHP、C#、Go、Ruby 等多种语言的 SDK:

本文以 Node.js 为例,介绍如何编写脚本导入用户,你可以选择自己熟悉的语言。

第一步:使用自定义密码函数(可选)

如果你的用户数据表中密码字段是明文,可以跳过此步骤;如果是密文,需要进入 基础配置 -> 密码管理 -> 自定义密码加密方法 开启选项并编写用于加密和验证密码的函数。详情请见 自定义密码加密方法

第二步:导出你的用户数据

请将你的用户数据导出为 JSON 格式,内容为一个数组,每个元素是一个对象,其中一个元素对应一条用户的信息,保存为例如 users.json:

json
[
  {
    "uid": "AUTHING_USER_1",
    "nickname": "zhang",
    "account_id": "zhang",
    "mail": "test1@123.com",
    "password": "$2b$12$nCa3WDbsc3tvM57ifzjwrOAGGuNK7EPV0R17WKcW6f13NZvX97yLe",
    "phone": "13100000001",
    "emailVerified": true,
    "loginsCount": 4
  },
  {
    "uid": "AUTHING_USER_2",
    "nickname": "wang",
    "account_id": "wang",
    "mail": "test2@123.com",
    "password": "$2b$12$HGloOlfz1HzD0v/r5m1r7OCMcx6X85eC5.At3Ckxe.Jn/u/Za/yy2",
    "phone": "13100000002",
    "emailVerified": false,
    "loginsCount": 12
  },
  {
    "uid": "AUTHING_USER_3",
    "nickname": "zhao",
    "account_id": "zhao",
    "mail": "test3@123.com",
    "password": "$2b$12$ia1oUZZFbEUpLvuqUsKideQq9lVkf2kq9vFaTvp7dlfeCx8UlTmDu",
    "phone": "13100000003",
    "emailVerified": true,
    "loginsCount": 0
  }
]

第三步:确认用户字段映射关系

在正式开始导入之前,你需要先确认你的用户结构与 GenAuth 用户字段之间的映射关系,你可以在这里获取 GenAuth 用户所有字段及其释义。

第四步:导入用户数据到 GenAuth

如果你没有 NodeJS 环境,需要先安装 NodeJS

创建一个 index.js 文件。

将以下 js 脚本粘贴到 index.js:

js
const fs = require('fs')
const path = require('path')

const { ManagementClient } = require('authing-js-sdk')
const userPoolId = 'xxxxxxxxxxxxxxxxxxx'
const secret = 'xxxxxxxxxxxxxxxxxxx'

// 如果文件较大建议分批次读入
// 请将用户信息与本文件保存在同一个目录,文件内容为用户数据的数组 JSON,一个元素为一个用户的信息对象,此处读取上文中的 users.json
let users = fs.readFileSync(path.resolve('users.json'), { encoding: 'utf8' })
users = JSON.parse(users)
async function main() {
  const managementClient = new ManagementClient({
    userPoolId,
    secret,
  })

  for (let i = 0; i < users.length; i++) {
    let yourUser = users[i]
    try {
      // 在此完成字段对齐
      await managementClient.users.create(
        {
          nickname: yourUser.nickname,
          password: yourUser.password,
          email: yourUser.mail,
          emailVerified: yourUser.emailVerified,
          phone: yourUser.phone,
          loginsCount: yourUser.loginsCount,
          // 存储原始数据,以备使用
          oauth: JSON.stringify(yourUser),
        },
        {
          /**
           * 开启这个开关,password 字段会直接写入 Authing 数据库,Authing 不会再次加密此字段
           * 如果你的密码不是明文存储,你应该保持开启,并编写密码函数计算
           */
          keepPassword: true,
        }
      )
    } catch (err) {
      console.log(err)
      // 将导入失败的用户写入文件
      fs.writeFileSync(
        path.resolve('users_failed.json'),
        JSON.stringify(yourUser) + '\n',
        {
          flag: 'a',
        }
      )
    }
  }
}

main()

复制完成后请对字段进行对齐,再执行

bash
$ npm install authing-js-sdk
$ node index.js

代码可在 GitHub 查看:users-migration

获取帮助

遇到问题?联系我们,Feel free to talk.

自定义密码加密方法

如果你想自定义密码加密函数,请在此上传函数片段(目前仅支持 Node.js),函数模版请点击这里下载(GenAuth 不会存储用户的密码原文)。

此功能适用于以下场景:

  1. 你将所有用户迁移进了 GenAuth,但不想让用户修改密码;
  2. 你不信任 GenAuth 的密码加密算法,想使用自己的密码加密算法;

本文档介绍了如何配置密码加密函数。

配置步骤

路径:安全设置->密码安全->自定义密码加密方法

如下图所示:

INFO

自定义密码加密方法

下载模版

点击页面中的 下载模版 下载 Node.js 代码模版,模版代码如下所示:

js
var getRawBody = require("raw-body");

const encryptPassword = (password) => {
  // 在此编写加密密码的函数

  return password;
};

/**
 *
 * @param {String} password 明文密码
 * @param {String} encryptedPassword 密文密码
 */
const comparePassword = (password, encryptedPassword) => {
  // 在此编写校验密码的函数

  return password === encryptedPassword;
};

module.exports.encrypt = function (request, response, context) {
  // get request body
  getRawBody(request, function (err, body) {
    const queries = request.queries;
    const password = queries.password;

    if (!password) {
      response.setStatusCode(500);
      response.setHeader("content-type", "application/json");
      response.send(
        JSON.stringify(
          {
            message: "Please provide password via url query",
          },
          null,
          4
        )
      );
    }

    const respBody = {
      password: encryptPassword(password), // 在此加密密码
    };

    response.setStatusCode(200);
    response.setHeader("content-type", "application/json");
    response.send(JSON.stringify(respBody, null, 4));
  });
};

module.exports.validate = function (request, response, context) {
  // get request body
  getRawBody(request, function (err, body) {
    const queries = request.queries;
    const password = queries.password;
    const encryptedPassword = queries.encryptedPassword;

    if (!password) {
      response.setStatusCode(500);
      response.setHeader("content-type", "application/json");
      response.send(
        JSON.stringify(
          {
            message: "Please provide password via url query",
          },
          null,
          4
        )
      );
    }

    const respBody = {
      isValid: comparePassword(password, encryptedPassword), // 在此校验密码
    };

    response.setStatusCode(200);
    response.setHeader("content-type", "application/json");
    response.send(JSON.stringify(respBody, null, 4));
  });
};

编写代码

你需要在 encryptPassword 函数中编写相应的密码加密方法,以及在 vlidatePassword 函数中编写相应的验证密码加密方法。

若开发者需要引入第三方 NPM 包,请直接使用 NPM 直接安装。

INFO

NPM 是 Node.js 生态的包管理工具。

以下是引入 bcryptjs 包的一个代码示例:

haskell
$ npm install bcryptjs

安装完成后在文件夹内会多出一个 node_modules 文件夹,之后编写代码:

js
var getRawBody = require("raw-body");

const encryptPassword = (password) => {
  // Implement your login here.
  // Your can use bcrypt for example
  // more info here: https://github.com/kelektiv/node.bcrypt.js
  var bcryptjs = require("bcryptjs");
  var genSaltSync = bcryptjs.genSaltSync();
  return bcryptjs.hashSync(password, genSaltSync);
};

const vlidatePassword = (plainText, encrypted) => {
  // plainText is the plainText password use provide to be validate.
  // encrypted is user's password encryped in database.

  // Implement your login here.
  // Your can use bcrypt for example
  // more info here: https://github.com/kelektiv/node.bcrypt.js
  var bcryptjs = require("bcryptjs");
  return bcryptjs.compareSync(password, encryptedPassword);
};

上传函数至服务器

INFO

GenAuth 支持的代码包只能为 .js 格式或 .zip 格式。

若你没有引入任何包,可直接上传 .js 格式的模版文件;若你引入了包请连带 node_modules 一起打包为 .zip 格式并在 GenAuth 控制台中上传。

测试密码加密函数

上传成功后开发者可测试密码加密效果,如下所示,在输入框中输入原密码后点击「加密测试」即可看到加密后的密码(若未上传任何加密函数将显示 GenAuth 默认的密码加密结果)。

示例代码

注意事项

INFO

密码加密函数上传后即生效,会影响原用户,建议此功能在完全新的用户池中使用。

若你需要在旧用户池中修改密码加密函数,请联系 GenAuth 售后服务人员

从企业微信、钉钉等第三方身份源导入用户

如果你属于内部员工的使用场景(EIAM),你可以从以下第三方身份源中导入组织机构与用户目录:

你可以分别点击链接阅读详细的指引流程。