Firebase Admin SDK 提供 Auth.importUsers()
API,可透過提升的權限將大量使用者匯入 Firebase Authentication。Firebase CLI 也提供這項功能,但使用 Admin SDK 時,您可以透過程式輔助方式,從外部驗證系統或其他 Firebase 專案上傳現有使用者,不必建立中繼 CSV 或 JSON 檔案。
使用者匯入 API 具有下列優點:
- 可使用不同的密碼雜湊演算法,從外部驗證系統遷移使用者。
- 可遷移其他 Firebase 專案的使用者。
- 最佳化大量匯入作業,提高速度和效率。這項作業會處理使用者,但不檢查
uid
、email
、phoneNumber
或其他 ID 是否重複。 - 能夠遷移現有或建立新的 OAuth 使用者 (Google、Facebook 等)。
- 可直接大量匯入具有自訂聲明的使用者。
用量
單一 API 呼叫最多可匯入 1,000 位使用者。請注意,這項作業已針對速度進行最佳化,不會檢查 uid
、email
、phoneNumber
和其他不重複 ID 是否重複。如果匯入的使用者與現有 uid
發生衝突,系統會取代現有使用者。如果匯入的使用者有任何其他重複的欄位 (例如 email
),系統會建立具有相同值的額外使用者。因此,使用這項 API 時,請務必確保沒有重複任何專屬欄位。
Node.js
// Up to 1000 users can be imported at once. const userImportRecords = [ { uid: 'uid1', email: '[email protected]', passwordHash: Buffer.from('passwordHash1'), passwordSalt: Buffer.from('salt1'), }, { uid: 'uid2', email: '[email protected]', passwordHash: Buffer.from('passwordHash2'), passwordSalt: Buffer.from('salt2'), }, //... ];
Java
// Up to 1000 users can be imported at once. List<ImportUserRecord> users = new ArrayList<>(); users.add(ImportUserRecord.builder() .setUid("uid1") .setEmail("[email protected]") .setPasswordHash("passwordHash1".getBytes()) .setPasswordSalt("salt1".getBytes()) .build()); users.add(ImportUserRecord.builder() .setUid("uid2") .setEmail("[email protected]") .setPasswordHash("passwordHash2".getBytes()) .setPasswordSalt("salt2".getBytes()) .build());
Python
# Up to 1000 users can be imported at once. users = [ auth.ImportUserRecord( uid='uid1', email='[email protected]', password_hash=b'password_hash_1', password_salt=b'salt1' ), auth.ImportUserRecord( uid='uid2', email='[email protected]', password_hash=b'password_hash_2', password_salt=b'salt2' ), ]
Go
// Up to 1000 users can be imported at once. var users []*auth.UserToImport users = append(users, (&auth.UserToImport{}). UID("uid1"). Email("[email protected]"). PasswordHash([]byte("passwordHash1")). PasswordSalt([]byte("salt1"))) users = append(users, (&auth.UserToImport{}). UID("uid2"). Email("[email protected]"). PasswordHash([]byte("passwordHash2")). PasswordSalt([]byte("salt2")))
C#
// Up to 1000 users can be imported at once. var users = new List<ImportUserRecordArgs>() { new ImportUserRecordArgs() { Uid = "uid1", Email = "[email protected]", PasswordHash = Encoding.ASCII.GetBytes("passwordHash1"), PasswordSalt = Encoding.ASCII.GetBytes("salt1"), }, new ImportUserRecordArgs() { Uid = "uid2", Email = "[email protected]", PasswordHash = Encoding.ASCII.GetBytes("passwordHash2"), PasswordSalt = Encoding.ASCII.GetBytes("salt2"), }, };
在本範例中,系統會指定雜湊選項,協助 Firebase 在使用者下次嘗試透過 Firebase Authentication 登入時,安全地驗證這些使用者。 成功登入後,Firebase 會使用內部 Firebase 雜湊演算法,重新雜湊處理使用者的密碼。請參閱下文,進一步瞭解各演算法的必填欄位。
Firebase Authentication 即使發生使用者專屬錯誤,仍會嘗試上傳所有提供的使用者。這項作業會傳回結果,其中包含匯入成功和失敗的摘要。系統會針對每個匯入失敗的使用者傳回錯誤詳細資料。
Node.js
getAuth() .importUsers(userImportRecords, { hash: { algorithm: 'HMAC_SHA256', key: Buffer.from('secretKey'), }, }) .then((userImportResult) => { // The number of successful imports is determined via: userImportResult.successCount. // The number of failed imports is determined via: userImportResult.failureCount. // To get the error details. userImportResult.errors.forEach((indexedError) => { // The corresponding user that failed to upload. console.log( 'Error ' + indexedError.index, ' failed to import: ', indexedError.error ); }); }) .catch((error) => { // Some unrecoverable error occurred that prevented the operation from running. });
Java
UserImportOptions options = UserImportOptions.withHash( HmacSha256.builder() .setKey("secretKey".getBytes()) .build()); try { UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); System.out.println("Successfully imported " + result.getSuccessCount() + " users"); System.out.println("Failed to import " + result.getFailureCount() + " users"); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user at index: " + indexedError.getIndex() + " due to error: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { // Some unrecoverable error occurred that prevented the operation from running. }
Python
hash_alg = auth.UserImportHash.hmac_sha256(key=b'secret_key') try: result = auth.import_users(users, hash_alg=hash_alg) print( f'Successfully imported {result.success_count} users. Failed to import ' f'{result.failure_count} users.') for err in result.errors: print(f'Failed to import {users[err.index].uid} due to {err.reason}') except exceptions.FirebaseError: # Some unrecoverable error occurred that prevented the operation from running. pass
Go
client, err := app.Auth(ctx) if err != nil { log.Fatalln("Error initializing Auth client", err) } h := hash.HMACSHA256{ Key: []byte("secretKey"), } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Unrecoverable error prevented the operation from running", err) } log.Printf("Successfully imported %d users\n", result.SuccessCount) log.Printf("Failed to import %d users\n", result.FailureCount) for _, e := range result.Errors { log.Printf("Failed to import user at index: %d due to error: %s\n", e.Index, e.Reason) }
C#
var options = new UserImportOptions() { Hash = new HmacSha256() { Key = Encoding.ASCII.GetBytes("secretKey"), }, }; try { UserImportResult result = await FirebaseAuth.DefaultInstance.ImportUsersAsync(users, options); Console.WriteLine($"Successfully imported {result.SuccessCount} users"); Console.WriteLine($"Failed to import {result.FailureCount} users"); foreach (ErrorInfo indexedError in result.Errors) { Console.WriteLine($"Failed to import user at index: {indexedError.Index}" + $" due to error: {indexedError.Reason}"); } } catch (FirebaseAuthException) { // Some unrecoverable error occurred that prevented the operation from running. }
如果不需要雜湊處理密碼 (電話號碼、自訂權杖使用者、OAuth 使用者等),請勿提供雜湊選項。
匯入使用 Firebase scrypt 雜湊密碼的使用者
根據預設,Firebase 會使用修改過的 Firebase 版 scrypt 雜湊演算法儲存密碼。匯入以修改過的 scrypt 雜湊處理的密碼,有助於從其他現有 Firebase 專案遷移使用者。如要執行這項作業,必須先為原始專案設定內部參數。
Firebase 會為每個 Firebase 專案產生專屬的密碼雜湊參數。如要存取這些參數,請前往 Firebase 控制台的「使用者」分頁,然後從使用者表格清單右上角的下拉式選單中選取「密碼雜湊參數」。
建構這個演算法的雜湊選項時,需要下列參數:
key
:簽署者金鑰,通常以 Base64 編碼提供。saltSeparator
:通常以 Base64 編碼提供的鹽分隔符(選用)。rounds
:用於雜湊處理密碼的回合數。memoryCost
:這個演算法所需的記憶體成本。
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: '[email protected]', // Must be provided in a byte buffer. passwordHash: Buffer.from('base64-password-hash', 'base64'), // Must be provided in a byte buffer. passwordSalt: Buffer.from('base64-salt', 'base64'), }, ], { hash: { algorithm: 'SCRYPT', // All the parameters below can be obtained from the Firebase Console's users section. // Must be provided in a byte buffer. key: Buffer.from('base64-secret', 'base64'), saltSeparator: Buffer.from('base64SaltSeparator', 'base64'), rounds: 8, memoryCost: 14, }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("[email protected]") .setPasswordHash(BaseEncoding.base64().decode("password-hash")) .setPasswordSalt(BaseEncoding.base64().decode("salt")) .build()); UserImportOptions options = UserImportOptions.withHash( Scrypt.builder() // All the parameters below can be obtained from the Firebase Console's "Users" // section. Base64 encoded parameters must be decoded into raw bytes. .setKey(BaseEncoding.base64().decode("base64-secret")) .setSaltSeparator(BaseEncoding.base64().decode("base64-salt-separator")) .setRounds(8) .setMemoryCost(14) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='[email protected]', password_hash=base64.urlsafe_b64decode('password_hash'), password_salt=base64.urlsafe_b64decode('salt') ), ] # All the parameters below can be obtained from the Firebase Console's "Users" # section. Base64 encoded parameters must be decoded into raw bytes. hash_alg = auth.UserImportHash.scrypt( key=base64.b64decode('base64_secret'), salt_separator=base64.b64decode('base64_salt_separator'), rounds=8, memory_cost=14 ) try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
b64URLdecode := func(s string) []byte { b, err := base64.URLEncoding.DecodeString(s) if err != nil { log.Fatalln("Failed to decode string", err) } return b } b64Stddecode := func(s string) []byte { b, err := base64.StdEncoding.DecodeString(s) if err != nil { log.Fatalln("Failed to decode string", err) } return b } // Users retrieved from Firebase Auth's backend need to be base64URL decoded users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("[email protected]"). PasswordHash(b64URLdecode("password-hash")). PasswordSalt(b64URLdecode("salt")), } // All the parameters below can be obtained from the Firebase Console's "Users" // section. Base64 encoded parameters must be decoded into raw bytes. h := hash.Scrypt{ Key: b64Stddecode("base64-secret"), SaltSeparator: b64Stddecode("base64-salt-separator"), Rounds: 8, MemoryCost: 14, } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
C#
try { var users = new List<ImportUserRecordArgs>() { new ImportUserRecordArgs() { Uid = "some-uid", Email = "[email protected]", PasswordHash = Encoding.ASCII.GetBytes("password-hash"), PasswordSalt = Encoding.ASCII.GetBytes("salt"), }, }; var options = new UserImportOptions() { // All the parameters below can be obtained from the Firebase Console's "Users" // section. Base64 encoded parameters must be decoded into raw bytes. Hash = new Scrypt() { Key = Encoding.ASCII.GetBytes("base64-secret"), SaltSeparator = Encoding.ASCII.GetBytes("base64-salt-separator"), Rounds = 8, MemoryCost = 14, }, }; UserImportResult result = await FirebaseAuth.DefaultInstance.ImportUsersAsync(users, options); foreach (ErrorInfo indexedError in result.Errors) { Console.WriteLine($"Failed to import user: {indexedError.Reason}"); } } catch (FirebaseAuthException e) { Console.WriteLine($"Error importing users: {e.Message}"); }
匯入具有標準 scrypt 雜湊密碼的使用者
Firebase Authentication 支援標準 scrypt 演算法和修改版 (如上)。如為標準 scrypt 演算法,則必須提供下列雜湊參數:
memoryCost
:雜湊演算法的 CPU/記憶體成本。parallelization
:雜湊演算法的平行化。blockSize
:雜湊演算法的區塊大小 (通常為 8)。derivedKeyLength
:雜湊演算法的衍生金鑰長度
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: '[email protected]', // 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); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("[email protected]") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash( StandardScrypt.builder() .setMemoryCost(1024) .setParallelization(16) .setBlockSize(8) .setDerivedKeyLength(64) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='[email protected]', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.standard_scrypt( memory_cost=1024, parallelization=16, block_size=8, derived_key_length=64) try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("[email protected]"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.StandardScrypt{ MemoryCost: 1024, Parallelization: 16, BlockSize: 8, DerivedKeyLength: 64, } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
C#
try { var users = new List<ImportUserRecordArgs>() { new ImportUserRecordArgs() { Uid = "some-uid", Email = "[email protected]", PasswordHash = Encoding.ASCII.GetBytes("password-hash"), PasswordSalt = Encoding.ASCII.GetBytes("salt"), }, }; var options = new UserImportOptions() { Hash = new StandardScrypt() { MemoryCost = 1024, Parallelization = 16, BlockSize = 8, DerivedKeyLength = 64, }, }; UserImportResult result = await FirebaseAuth.DefaultInstance.ImportUsersAsync(users, options); foreach (ErrorInfo indexedError in result.Errors) { Console.WriteLine($"Failed to import user: {indexedError.Reason}"); } } catch (FirebaseAuthException e) { Console.WriteLine($"Error importing users: {e.Message}"); }
匯入含有 HMAC 雜湊密碼的使用者
HMAC 雜湊演算法包括:HMAC_MD5
、HMAC_SHA1
、HMAC_SHA256
和 HMAC_SHA512
。對於這些雜湊演算法,您必須提供雜湊簽署者金鑰。
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: '[email protected]', // 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: 'HMAC_SHA256', // Must be provided in a byte buffer. key: Buffer.from('secret'), }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("[email protected]") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash( HmacSha256.builder() .setKey("secret".getBytes()) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='[email protected]', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.hmac_sha256(key=b'secret') try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("[email protected]"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.HMACSHA256{ Key: []byte("secret"), } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
C#
try { var users = new List<ImportUserRecordArgs>() { new ImportUserRecordArgs() { Uid = "some-uid", Email = "[email protected]", PasswordHash = Encoding.ASCII.GetBytes("password-hash"), PasswordSalt = Encoding.ASCII.GetBytes("salt"), }, }; var options = new UserImportOptions() { Hash = new HmacSha256() { Key = Encoding.ASCII.GetBytes("secret"), }, }; UserImportResult result = await FirebaseAuth.DefaultInstance.ImportUsersAsync(users, options); foreach (ErrorInfo indexedError in result.Errors) { Console.WriteLine($"Failed to import user: {indexedError.Reason}"); } } catch (FirebaseAuthException e) { Console.WriteLine($"Error importing users: {e.Message}"); }
匯入使用 MD5、SHA 和 PBKDF 雜湊密碼的使用者
MD5、SHA 和 PBKDF 雜湊演算法包括:MD5
、SHA1
、SHA256
、SHA512
、PBKDF_SHA1
和 PBKDF2_SHA256
。使用這些雜湊演算法時,您必須提供用於雜湊密碼的回合數 (MD5
為 0 到 8192 之間,SHA1
、SHA256
和 SHA512
為 1 到 8192 之間,PBKDF_SHA1
和 PBKDF2_SHA256
為 0 到 120000 之間)。
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: '[email protected]', // 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: 'PBKDF2_SHA256', rounds: 100000, }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("[email protected]") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash( Pbkdf2Sha256.builder() .setRounds(100000) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='[email protected]', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.pbkdf2_sha256(rounds=100000) try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("[email protected]"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.PBKDF2SHA256{ Rounds: 100000, } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
C#
try { var users = new List<ImportUserRecordArgs>() { new ImportUserRecordArgs() { Uid = "some-uid", Email = "[email protected]", PasswordHash = Encoding.ASCII.GetBytes("password-hash"), PasswordSalt = Encoding.ASCII.GetBytes("salt"), }, }; var options = new UserImportOptions() { Hash = new Pbkdf2Sha256() { Rounds = 100000, }, }; UserImportResult result = await FirebaseAuth.DefaultInstance.ImportUsersAsync(users, options); foreach (ErrorInfo indexedError in result.Errors) { Console.WriteLine($"Failed to import user: {indexedError.Reason}"); } } catch (FirebaseAuthException e) { Console.WriteLine($"Error importing users: {e.Message}"); }
匯入使用 BCRYPT 雜湊密碼的使用者
如果是 BCRYPT 雜湊密碼,則不需要額外的雜湊參數,也不需要為每位使用者設定密碼鹽。
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: '[email protected]', // Must be provided in a byte buffer. passwordHash: Buffer.from('password-hash'), }, ], { hash: { algorithm: 'BCRYPT', }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("[email protected]") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash(Bcrypt.getInstance()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='[email protected]', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.bcrypt() try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("[email protected]"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.Bcrypt{} result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
C#
try { var users = new List<ImportUserRecordArgs>() { new ImportUserRecordArgs() { Uid = "some-uid", Email = "[email protected]", PasswordHash = Encoding.ASCII.GetBytes("password-hash"), PasswordSalt = Encoding.ASCII.GetBytes("salt"), }, }; var options = new UserImportOptions() { Hash = new Bcrypt(), }; UserImportResult result = await FirebaseAuth.DefaultInstance.ImportUsersAsync(users, options); foreach (ErrorInfo indexedError in result.Errors) { Console.WriteLine($"Failed to import user: {indexedError.Reason}"); } } catch (FirebaseAuthException e) { Console.WriteLine($"Error importing users: {e.Message}"); }
匯入使用 Argon2 雜湊密碼的使用者
您可以建構 Argon2
雜湊物件,匯入含有 Argon2 雜湊密碼的使用者記錄。請注意,目前只有 Admin Java SDK 支援這項功能。
建構這個演算法的雜湊選項時,需要下列參數:
hashLengthBytes
:以位元組為單位的所需雜湊長度,以整數形式提供hashType
:要使用的 Argon2 變體 (ARGON2_D
、ARGON2_ID
、ARGON2_I
)parallelism
:平行處理作業程度,以整數形式提供。必須介於 1 到 16 之間 (含 1 和 16)iterations
:要執行的疊代次數,以整數形式提供。必須介於 1 到 16 之間 (含 1 和 16)memoryCostKib
:此演算法所需的記憶體成本 (以千位元組為單位),必須小於 32768。version
:Argon2 演算法版本 (VERSION_10
或VERSION_13
)。這是選用參數,如未指定,預設為 VERSION_13。associatedData
:以位元組陣列形式提供的額外關聯資料,會附加至雜湊值,提供額外一層安全防護。(選用) 這項資料會先經過 Base64 編碼,再傳送至 API。
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("[email protected]") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash( Argon2.builder() .setHashLengthBytes(512) .setHashType(Argon2HashType.ARGON2_ID) .setParallelism(8) .setIterations(16) .setMemoryCostKib(2048) .setVersion(Argon2Version.VERSION_10) .setAssociatedData("associated-data".getBytes()) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
匯入沒有密碼的使用者
您可以匯入沒有密碼的使用者。沒有密碼的使用者可以與有 OAuth 提供者、自訂聲明和電話號碼等的使用者一併匯入。
Node.js
getAuth() .importUsers([ { uid: 'some-uid', displayName: 'John Doe', email: '[email protected]', photoURL: 'http://www.example.com/12345678/photo.png', emailVerified: true, phoneNumber: '+11234567890', // Set this user as admin. customClaims: { admin: true }, // User with Google provider. providerData: [ { uid: 'google-uid', email: '[email protected]', displayName: 'John Doe', photoURL: 'http://www.example.com/12345678/photo.png', providerId: 'google.com', }, ], }, ]) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setDisplayName("John Doe") .setEmail("[email protected]") .setPhotoUrl("http://www.example.com/12345678/photo.png") .setEmailVerified(true) .setPhoneNumber("+11234567890") .putCustomClaim("admin", true) // set this user as admin .addUserProvider(UserProvider.builder() // user with Google provider .setUid("google-uid") .setEmail("[email protected]") .setDisplayName("John Doe") .setPhotoUrl("http://www.example.com/12345678/photo.png") .setProviderId("google.com") .build()) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', display_name='John Doe', email='[email protected]', photo_url='http://www.example.com/12345678/photo.png', email_verified=True, phone_number='+11234567890', custom_claims={'admin': True}, # set this user as admin provider_data=[ # user with Google provider auth.UserProvider( uid='google-uid', email='[email protected]', display_name='John Doe', photo_url='http://www.example.com/12345678/photo.png', provider_id='google.com' ) ], ), ] try: result = auth.import_users(users) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). DisplayName("John Doe"). Email("[email protected]"). PhotoURL("http://www.example.com/12345678/photo.png"). EmailVerified(true). PhoneNumber("+11234567890"). CustomClaims(map[string]interface{}{"admin": true}). // set this user as admin ProviderData([]*auth.UserProvider{ // user with Google provider { UID: "google-uid", Email: "[email protected]", DisplayName: "John Doe", PhotoURL: "http://www.example.com/12345678/photo.png", ProviderID: "google.com", }, }), } result, err := client.ImportUsers(ctx, users) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
C#
try { var users = new List<ImportUserRecordArgs>() { new ImportUserRecordArgs() { Uid = "some-uid", DisplayName = "John Doe", Email = "[email protected]", PhotoUrl = "http://www.example.com/12345678/photo.png", EmailVerified = true, PhoneNumber = "+11234567890", CustomClaims = new Dictionary<string, object>() { { "admin", true }, // set this user as admin }, UserProviders = new List<UserProvider> { new UserProvider() // user with Google provider { Uid = "google-uid", Email = "[email protected]", DisplayName = "John Doe", PhotoUrl = "http://www.example.com/12345678/photo.png", ProviderId = "google.com", }, }, }, }; UserImportResult result = await FirebaseAuth.DefaultInstance.ImportUsersAsync(users); foreach (ErrorInfo indexedError in result.Errors) { Console.WriteLine($"Failed to import user: {indexedError.Reason}"); } } catch (FirebaseAuthException e) { Console.WriteLine($"Error importing users: {e.Message}"); }