【问题标题】:Can I use the auth:import and auth:export tools with the Firebase Auth Emulator?我可以将 auth:import 和 auth:export 工具与 Firebase Auth Emulator 一起使用吗?
【发布时间】:2021-02-22 12:40:25
【问题描述】:

我想在 firebase auth 模拟器启动时使用我的测试用户帐户预加载它,就像我为 Firestore 模拟器及其导入/导出选项所做的那样。我在模拟器运行时尝试使用 auth:import 和 auth:export,但它连接到我们实际的开发 firebase 项目,而不是模拟器。是否有针对 auth 模拟器运行 auth:import 和 auth:export 的方法?

作为参考,我指的是这些命令 (https://firebase.google.com/docs/cli/auth) 和这个模拟器 (https://firebase.google.com/docs/emulator-suite/connect_auth)。

【问题讨论】:

标签: firebase firebase-authentication firebase-tools


【解决方案1】:

完成此操作的最简单方法是在运行模拟器时传入--export-on-exit,例如:firebase emulators:start --export-on-exit .firebase-emulators,它将在退出模拟器时将所有测试数据转储到指定目录中。

然后,您可以根据需要将其检入源代码(确保模拟器中没有敏感数据),并在每次启动时执行firebase emulators:start --import .firebase-emulators 阅读。

【讨论】:

    【解决方案2】:

    Firebase 工具现已添加了执行此操作的功能

    旧的答案仍然有效,可能有用

    https://github.com/firebase/firebase-tools/releases/tag/v9.1.0

    支持模拟器:Auth Emulator (#2955) 的导出和导入。

    https://github.com/firebase/firebase-tools/pull/2955

    firebase help auth:import
    Usage: firebase auth:import [options] [dataFile]
    
    import users into your Firebase project from a data file(.csv or .json)
    
    Options:
      --hash-algo <hashAlgo>               specify the hash algorithm used in password for these accounts
      --hash-key <hashKey>                 specify the key used in hash algorithm
      --salt-separator <saltSeparator>     specify the salt separator which will be appended to salt when verifying password. only used by SCRYPT now.
      --rounds <rounds>                    specify how many rounds for hash calculation.
      --mem-cost <memCost>                 specify the memory cost for firebase scrypt, or cpu/memory cost for standard scrypt
      --parallelization <parallelization>  specify the parallelization for standard scrypt.
      --block-size <blockSize>             specify the block size (normally is 8) for standard scrypt.
      --dk-len <dkLen>                     specify derived key length for standard scrypt.
      --hash-input-order <hashInputOrder>  specify the order of password and salt. Possible values are SALT_FIRST and PASSWORD_FIRST. MD5, SHA1, SHA256, SHA512, HMAC_MD5, HMAC_SHA1, HMAC_SHA256, HMAC_SHA512 support this flag.
      -h, --help                           output usage information
    

    【讨论】:

    • 既然功能已经存在,您如何实际将身份验证导入实现到模拟器中?我似乎找不到任何明确的文档/示例。例如,目前要导入 Firestore 数据库,我有一个以前使用的数据库导出:firebase emulators:start --import=./backups/$DB_ENV/db 我会添加什么来拉入例如存储在文件中的身份验证导出:auth.json
    • 我自己还没有尝试过,但我现在已经在上面添加了命令帮助
    • 谢谢肖恩。为了解决我的特定身份验证导入问题,我最终运行了firebase emulators:export ./backups/emulator,这会生成模拟器在导入期间寻找的新更新的元数据文件和文件夹结构——如果你使用的是最新版本,这包括一个auth_export 文件夹。所以现在我只需镜像该文件/文件夹结构,就可以将实时数据迁移到模拟器中。快乐的日子!
    【解决方案3】:

    https://firebase.google.com/docs/auth/admin/import-users#import_users_with_standard_scrypt_hashed_passwords

    admin
      .auth()
      .importUsers(
        [
          {
            uid: 'some-uid',
            email: 'user@example.com',
            // Must be provided in a byte buffer.
            passwordHash: Buffer.from('password-hash'),
            // Must be provided in a byte buffer.
            passwordSalt: Buffer.from('salt'),
          },
        ],
        {
          hash: {
            algorithm: 'STANDARD_SCRYPT',
            memoryCost: 1024,
            parallelization: 16,
            blockSize: 8,
            derivedKeyLength: 64,
          },
        }
      )
      .then((results) => {
        results.errors.forEach((indexedError) => {
          console.log(`Error importing user ${indexedError.index}`);
        });
      })
      .catch((error) => {
        console.log('Error importing users :', error);
      });
    

    【讨论】:

      【解决方案4】:

      感谢@alex-egli,这很有帮助

      这是我的版本,基于你的版本,有 3 个小改动

      1. 避免 eslint 警告 https://eslint.org/docs/rules/no-await-in-loop
        (我不认为你的代码在这里不好,警告可以被静音)

      2. 添加检查是否正在模拟器上运行

      3. 添加了用户显示名称

      exports.populateAuthUsers = functions.https.onRequest(async (req, res) => {
        if (!process.env["FUNCTIONS_EMULATOR"]) {
          return res
            .status(403)
            .send("ACCESS DENIED. This function is ONLY available via an emulator");
        }
        const users = [
          {
            uid: "user1",
            displayName: "one Local Admin",
            email: "one@test.com",
            password: "password",
          },
          {
            uid: "user2",
            displayName: "two Local Admin",
            email: "two@test.com",
            password: "password",
          },
          // put all test users you want populated here
        ];
      
        const results = [];
        const promises = [];
        for (let user of users) {
          let promise = admin
            .auth()
            .createUser(user)
            .then((result) => {
              return result;
            })
            .catch((error) => {
              return error.message; // continue on errors (eg duplicate users)
            });
      
          promises.push(promise);
        }
        await Promise.all(promises).then((result) => {
          results.push(result);
          return;
        });
        res.header("Content-type", "application/json");
        return res.status(200).send(JSON.stringify(results));
      });
      
      

      【讨论】:

      • 我真的很喜欢你的模拟器检查,我要把它添加到我的本地代码中。我故意以串行方式添加我的用户,因为在我的情况下,我要添加几百个用户,并且我不想使可用连接或本地资源的数量超载。如果您添加的数量少于 100 个,那么以您在这里的方式并行执行可能是最好的。
      • 如何执行这个动作?在某些脚本中还是来自我的应用程序代码?
      • 本示例使用了云函数firebase.google.com/docs/functions/get-started,但请注意,您现在可以通过模拟器直接导入和导出身份验证数据stackoverflow.com/a/65754945/1537692
      • 这仍然会更新生产有什么原因吗?选择模拟器需要什么 firebase-admin 版本?所有其他功能都在更新模拟器
      【解决方案5】:

      由于 firebase 确认不支持此功能,因此我使用了云功能来执行此操作。我首先将我希望在启动时加载的用户导出为 json 格式,然后在每次重启模拟器时运行此云功能:

      exports.populateAuthUsers = functions.https.onRequest(async (req, res) => {
      
        try {
          admin.initializeApp();
          
          const users = [
            { uid: "user1", email: "user1@test.com", password: "password" },
            // put all test users you want populated here
          ];
      
          const results = [];
          for (let user of users) {
            const result = await admin.auth().createUser(user);
            results.push(result);
          }
      
          return res.status(200).send(results);
        } catch (error) {
          console.error('Error: ', error);
          return res.status(500).send(error);
        }
      });
      

      即使有几百个用户,也只需几秒钟即可运行。只要确保永远不要将其部署到任何实际的 firebase 环境!仅供本地使用。

      【讨论】:

      • 你如何执行这个?
      • 我建议现在使用随身份验证模拟器提供的内置工具,正如 Sean Burlington 所提到的。如果您仍然喜欢使用云功能,那么您可以通过对您的云功能运行正常的 GET 请求来执行它。每当我的模拟器启动时,我通常只需按 ctrl+单击在我的终端中发布的此云功能的 url。启动模拟器时,应列出所有云函数 url。
      猜你喜欢
      • 2018-04-07
      • 2020-04-21
      • 2023-03-24
      • 2021-08-23
      • 2017-08-04
      • 1970-01-01
      • 2021-12-04
      • 2018-04-08
      • 1970-01-01
      相关资源
      最近更新 更多