Admin SDK를 사용하면 전체 관리자 권한이나 보다 세분화된 제한된 권한으로 실시간 데이터베이스 데이터를 읽고 쓸 수 있습니다. 이 문서에서는 Firebase Realtime Database 액세스를 위해 프로젝트에 Firebase Admin SDK를 추가하는 방법을 설명합니다.
Admin SDK 설정
서버에서 Firebase 실시간 데이터베이스를 시작하려면 우선 원하는 언어로 Firebase Admin SDK를 설정해야 합니다.
Admin SDK 인증
서버에서 Firebase Admin SDK를 사용하여 Firebase Realtime Database에 액세스하려면 먼저 Firebase로 서버를 인증해야 합니다. 서버 인증 시 클라이언트 앱처럼 사용자 계정의 사용자 인증 정보로 로그인하는 것이 아니라 서버를 Firebase에서 식별할 수 있도록 서비스 계정으로 인증합니다.
Firebase Admin SDK를 사용하여 인증할 때는 다음과 같이 2가지 수준의 액세스가 있습니다.
Firebase Admin SDK 인증 액세스 수준 | |
---|---|
관리자 권한 | 프로젝트의 Realtime Database 전체를 읽고 쓸 수 있습니다. 데이터 마이그레이션 또는 재구성과 같이 프로젝트의 리소스에 무제한으로 액세스해야 하는 관리 작업을 실행하는 데 사용되며 신중하게 사용해야 합니다. |
제한된 권한 | 프로젝트의 Realtime Database에 대한 액세스 권한은 서버에 필요한 리소스로만 제한됩니다. 액세스 요구사항이 명확하게 정의된 관리 작업을 실행하는 데 사용됩니다. 예를 들어 전체 데이터베이스에서 데이터를 읽는 요약 작업을 실행할 때 읽기 전용 보안 규칙을 설정한 후 이 규칙으로 제한된 권한을 사용해 Admin SDK를 초기화하면 의도하지 않은 쓰기를 방지할 수 있습니다. |
관리자 권한으로 인증
Firebase 프로젝트에서 편집자 역할을 갖는 서비스 계정의 인증 정보로 Firebase Admin SDK를 초기화하면 해당 인스턴스는 프로젝트의 Realtime Database 전체에 대해 읽기 및 쓰기 권한을 갖습니다.
자바
// Fetch the service account key JSON file contents FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccount.json"); // Initialize the app with a service account, granting admin privileges FirebaseOptions options = FirebaseOptions.builder() .setCredentials(GoogleCredentials.fromStream(serviceAccount)) // The database URL depends on the location of the database .setDatabaseUrl("https://DATABASE_NAME.firebaseio.com") .build(); FirebaseApp.initializeApp(options); // As an admin, the app has access to read and write all data, regardless of Security Rules DatabaseReference ref = FirebaseDatabase.getInstance() .getReference("restricted_access/secret_document"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Object document = dataSnapshot.getValue(); System.out.println(document); } @Override public void onCancelled(DatabaseError error) { } });
Node.js
var admin = require("firebase-admin"); // Fetch the service account key JSON file contents var serviceAccount = require("path/to/serviceAccountKey.json"); // Initialize the app with a service account, granting admin privileges admin.initializeApp({ credential: admin.credential.cert(serviceAccount), // The database URL depends on the location of the database databaseURL: "https://DATABASE_NAME.firebaseio.com" }); // As an admin, the app has access to read and write all data, regardless of Security Rules var db = admin.database(); var ref = db.ref("restricted_access/secret_document"); ref.once("value", function(snapshot) { console.log(snapshot.val()); });
Python
import firebase_admin from firebase_admin import credentials from firebase_admin import db # Fetch the service account key JSON file contents cred = credentials.Certificate('path/to/serviceAccountKey.json') # Initialize the app with a service account, granting admin privileges firebase_admin.initialize_app(cred, { 'databaseURL': 'https://databaseName.firebaseio.com' }) # As an admin, the app has access to read and write all data, regradless of Security Rules ref = db.reference('restricted_access/secret_document') print(ref.get())
Go
ctx := context.Background() conf := &firebase.Config{ DatabaseURL: "https://databaseName.firebaseio.com", } // Fetch the service account key JSON file contents opt := option.WithCredentialsFile("path/to/serviceAccountKey.json") // Initialize the app with a service account, granting admin privileges app, err := firebase.NewApp(ctx, conf, opt) if err != nil { log.Fatalln("Error initializing app:", err) } client, err := app.Database(ctx) if err != nil { log.Fatalln("Error initializing database client:", err) } // As an admin, the app has access to read and write all data, regradless of Security Rules ref := client.NewRef("restricted_access/secret_document") var data map[string]interface{} if err := ref.Get(ctx, &data); err != nil { log.Fatalln("Error reading from database:", err) } fmt.Println(data)
제한된 권한으로 인증
필요한 리소스에 대한 권한만 부여하는 것이 좋습니다. Firebase 앱 인스턴스가 액세스할 수 있는 리소스를 보다 세밀하게 제어하려면 보안 규칙에서 고유 식별자를 사용하여 서비스를 나타냅니다. 그런 다음 적절한 규칙을 설정하여 필요한 리소스에 대한 권한을 서비스에 부여합니다. 예를 들면 다음과 같습니다.
{ "rules": { "public_resource": { ".read": true, ".write": true }, "some_resource": { ".read": "auth.uid === 'my-service-worker'", ".write": false }, "another_resource": { ".read": "auth.uid === 'my-service-worker'", ".write": "auth.uid === 'my-service-worker'" } } }
그런 다음 서버에서 Firebase 앱을 초기화할 때 databaseAuthVariableOverride
옵션을 사용하여 데이터베이스 규칙에 사용되는 auth
객체를 재정의합니다. 이 커스텀 auth
객체의 uid
필드를 보안 규칙에서 서비스를 나타내는 데 사용한 식별자로 설정합니다.
자바
// Fetch the service account key JSON file contents FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountCredentials.json"); // Initialize the app with a custom auth variable, limiting the server's access Map<String, Object> auth = new HashMap<String, Object>(); auth.put("uid", "my-service-worker"); FirebaseOptions options = new FirebaseOptions.Builder() .setCredential(FirebaseCredentials.fromCertificate(serviceAccount)) // The database URL depends on the location of the database .setDatabaseUrl("https://DATABASE_NAME.firebaseio.com") .setDatabaseAuthVariableOverride(auth) .build(); FirebaseApp.initializeApp(options); // The app only has access as defined in the Security Rules DatabaseReference ref = FirebaseDatabase .getInstance() .getReference("/some_resource"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { String res = dataSnapshot.getValue(); System.out.println(res); } });
Node.js
var admin = require("firebase-admin"); // Fetch the service account key JSON file contents var serviceAccount = require("path/to/serviceAccountKey.json"); // Initialize the app with a custom auth variable, limiting the server's access admin.initializeApp({ credential: admin.credential.cert(serviceAccount), // The database URL depends on the location of the database databaseURL: "https://DATABASE_NAME.firebaseio.com", databaseAuthVariableOverride: { uid: "my-service-worker" } }); // The app only has access as defined in the Security Rules var db = admin.database(); var ref = db.ref("/some_resource"); ref.once("value", function(snapshot) { console.log(snapshot.val()); });
Python
import firebase_admin from firebase_admin import credentials from firebase_admin import db # Fetch the service account key JSON file contents cred = credentials.Certificate('path/to/serviceAccountKey.json') # Initialize the app with a custom auth variable, limiting the server's access firebase_admin.initialize_app(cred, { 'databaseURL': 'https://databaseName.firebaseio.com', 'databaseAuthVariableOverride': { 'uid': 'my-service-worker' } }) # The app only has access as defined in the Security Rules ref = db.reference('/some_resource') print(ref.get())
Go
ctx := context.Background() // Initialize the app with a custom auth variable, limiting the server's access ao := map[string]interface{}{"uid": "my-service-worker"} conf := &firebase.Config{ DatabaseURL: "https://databaseName.firebaseio.com", AuthOverride: &ao, } // Fetch the service account key JSON file contents opt := option.WithCredentialsFile("path/to/serviceAccountKey.json") app, err := firebase.NewApp(ctx, conf, opt) if err != nil { log.Fatalln("Error initializing app:", err) } client, err := app.Database(ctx) if err != nil { log.Fatalln("Error initializing database client:", err) } // The app only has access as defined in the Security Rules ref := client.NewRef("/some_resource") var data map[string]interface{} if err := ref.Get(ctx, &data); err != nil { log.Fatalln("Error reading from database:", err) } fmt.Println(data)
경우에 따라서는 Admin SDK의 범위를 줄여 미인증 클라이언트로 작동하게 할 수 있습니다. 이렇게 하려면 데이터베이스 auth 변수 재정의에 null
값을 제공합니다.
자바
// Fetch the service account key JSON file contents FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountCredentials.json"); FirebaseOptions options = new FirebaseOptions.Builder() .setCredential(FirebaseCredentials.fromCertificate(serviceAccount)) // The database URL depends on the location of the database .setDatabaseUrl("https://DATABASE_NAME.firebaseio.com") .setDatabaseAuthVariableOverride(null) .build(); FirebaseApp.initializeApp(options); // The app only has access to public data as defined in the Security Rules DatabaseReference ref = FirebaseDatabase .getInstance() .getReference("/public_resource"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { String res = dataSnapshot.getValue(); System.out.println(res); } });
Node.js
var admin = require("firebase-admin"); // Fetch the service account key JSON file contents var serviceAccount = require("path/to/serviceAccountKey.json"); // Initialize the app with a null auth variable, limiting the server's access admin.initializeApp({ credential: admin.credential.cert(serviceAccount), // The database URL depends on the location of the database databaseURL: "https://DATABASE_NAME.firebaseio.com", databaseAuthVariableOverride: null }); // The app only has access to public data as defined in the Security Rules var db = admin.database(); var ref = db.ref("/public_resource"); ref.once("value", function(snapshot) { console.log(snapshot.val()); });
Python
import firebase_admin from firebase_admin import credentials from firebase_admin import db # Fetch the service account key JSON file contents cred = credentials.Certificate('path/to/serviceAccountKey.json') # Initialize the app with a None auth variable, limiting the server's access firebase_admin.initialize_app(cred, { 'databaseURL': 'https://databaseName.firebaseio.com', 'databaseAuthVariableOverride': None }) # The app only has access to public data as defined in the Security Rules ref = db.reference('/public_resource') print(ref.get())
Go
ctx := context.Background() // Initialize the app with a nil auth variable, limiting the server's access var nilMap map[string]interface{} conf := &firebase.Config{ DatabaseURL: "https://databaseName.firebaseio.com", AuthOverride: &nilMap, } // Fetch the service account key JSON file contents opt := option.WithCredentialsFile("path/to/serviceAccountKey.json") app, err := firebase.NewApp(ctx, conf, opt) if err != nil { log.Fatalln("Error initializing app:", err) } client, err := app.Database(ctx) if err != nil { log.Fatalln("Error initializing database client:", err) } // The app only has access to public data as defined in the Security Rules ref := client.NewRef("/some_resource") var data map[string]interface{} if err := ref.Get(ctx, &data); err != nil { log.Fatalln("Error reading from database:", err) } fmt.Println(data)
다음 단계
- Realtime Database의 데이터를 구조화하는 방법 알아보기
- 여러 데이터베이스 인스턴스에서 데이터 규모 조정
- 데이터 저장
- 데이터 검색
- Firebase Console에서 데이터베이스 보기