Android

[Firestore Database] 파이어베이스 Caused by: io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions. 권한 오류 해결하기

파이어베이스에서 제공하는 데이터베이스 중에 Firestore 데이터베이스를 사용해보기 위해

파이어베이스 콘솔에 접근하여 데이터 탭에서 컬렉션 하나를 생성하였다. 


그리고 가이드 문서에 따라 개발환경을 구성하였다.

dependencies {
    // Import the BoM for the Firebase platform
    implementation platform('com.google.firebase:firebase-bom:29.0.0')

    // Declare the dependency for the Cloud Firestore library
    // When using the BoM, you don't specify versions in Firebase library dependencies
    implementation 'com.google.firebase:firebase-firestore'
}

 

아래 코드처러미 인스턴스를 초기화 하고 데이터를 추가해 보았다.

Cloud Firestore는 컬렉션에 저장되는 문서에 데이터를 저장한다.
문서에 데이터를 처음 추가할 때 Cloud Firestore에서 암시적으로 컬렉션과 문서를 만든다.
컬렉션이나 문서를 명시적으로 만들 필요는 없다.

    private FirebaseFirestore db;
    final String TAG = "FireStore";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ranking);

        setup();
        setDocument();
    }
    
    
    public void setup() {
        // [START get_firestore_instance]
        db = FirebaseFirestore.getInstance();
        // [END get_firestore_instance]

        // [START set_firestore_settings]
        FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
                .setPersistenceEnabled(true)
                .build();
        db.setFirestoreSettings(settings);
        // [END set_firestore_settings]

    }
    
    public void setDocument() {
        // [START set_document]
        Map<String, Object> todaySteps = new HashMap<>();
        todaySteps.put("activateTime", "20");
        todaySteps.put("date", "2022.02.06");
        todaySteps.put("nickId", "CHK123USA");
        todaySteps.put("nickName", "홍길동");
        todaySteps.put("step", "860");

        // Add a new document with a generated ID
        db.collection("ranking")
                .add(todaySteps)
                .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                    @Override
                    public void onSuccess(DocumentReference documentReference) {
                        Log.d(TAG, "DocumentSnapshot added with ID: " + documentReference.getId());
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.w(TAG, "Error adding document", e);
                    }
                });
                
                
        db.collection("ranking").document("document-id")
                .set(todaySteps)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.d(TAG, "################################ DocumentSnapshot successfully written!");
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.w(TAG, "############################# Error writing document", e);
                    }
                });
//         [END set_document]


        // [START set_with_id]
//        db.collection("ranking").document("document-id").set(todaySteps);
        // [END set_with_id]
    }

그러나 Permission denied 오류가 발생하였다.
역시 접근하려면 로그인이 필요한 것인가?

 
    com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
        at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:117)
        at com.google.firebase.firestore.core.SyncEngine.notifyUser(SyncEngine.java:575)
        at com.google.firebase.firestore.core.SyncEngine.handleRejectedWrite(SyncEngine.java:457)
        at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedWrite(MemoryComponentProvider.java:114)
        at com.google.firebase.firestore.remote.RemoteStore.handleWriteError(RemoteStore.java:729)
        at com.google.firebase.firestore.remote.RemoteStore.handleWriteStreamClose(RemoteStore.java:685)
        at com.google.firebase.firestore.remote.RemoteStore.access$600(RemoteStore.java:53)
        at com.google.firebase.firestore.remote.RemoteStore$2.onClose(RemoteStore.java:206)
        at com.google.firebase.firestore.remote.AbstractStream.close(AbstractStream.java:356)
        at com.google.firebase.firestore.remote.AbstractStream.handleServerClose(AbstractStream.java:410)
        at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onClose$3$AbstractStream$StreamObserver(AbstractStream.java:151)
        at com.google.firebase.firestore.remote.-$$Lambda$AbstractStream$StreamObserver$CiUxcjPbqaWvp6DcUxZC1He8ANY.run(Unknown Source:4)
        at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67)
        at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onClose(AbstractStream.java:137)
        at com.google.firebase.firestore.remote.FirestoreChannel$1.onClose(FirestoreChannel.java:142)
        at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java:463)
        at io.grpc.internal.DelayedClientCall$DelayedListener.delayOrExecute(DelayedClientCall.java:427)
        at io.grpc.internal.DelayedClientCall$DelayedListener.onClose(DelayedClientCall.java:460)
        at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:557)
        at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:69)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:738)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:717)
        at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
        at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:234)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions.
        at io.grpc.Status.asException(Status.java:543)
        at com.google.firebase.firestore.util.Util.exceptionFromStatus(Util.java:115)
        at com.google.firebase.firestore.core.SyncEngine.notifyUser(SyncEngine.java:575) 
        at com.google.firebase.firestore.core.SyncEngine.handleRejectedWrite(SyncEngine.java:457) 
        at com.google.firebase.firestore.core.MemoryComponentProvider$RemoteStoreCallback.handleRejectedWrite(MemoryComponentProvider.java:114) 
        at com.google.firebase.firestore.remote.RemoteStore.handleWriteError(RemoteStore.java:729) 
        at com.google.firebase.firestore.remote.RemoteStore.handleWriteStreamClose(RemoteStore.java:685) 
        at com.google.firebase.firestore.remote.RemoteStore.access$600(RemoteStore.java:53) 
        at com.google.firebase.firestore.remote.RemoteStore$2.onClose(RemoteStore.java:206) 
        at com.google.firebase.firestore.remote.AbstractStream.close(AbstractStream.java:356) 
        at com.google.firebase.firestore.remote.AbstractStream.handleServerClose(AbstractStream.java:410) 
        at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.lambda$onClose$3$AbstractStream$StreamObserver(AbstractStream.java:151) 
        at com.google.firebase.firestore.remote.-$$Lambda$AbstractStream$StreamObserver$CiUxcjPbqaWvp6DcUxZC1He8ANY.run(Unknown Source:4) 
        at com.google.firebase.firestore.remote.AbstractStream$CloseGuardedRunner.run(AbstractStream.java:67) 
        at com.google.firebase.firestore.remote.AbstractStream$StreamObserver.onClose(AbstractStream.java:137) 
        at com.google.firebase.firestore.remote.FirestoreChannel$1.onClose(FirestoreChannel.java:142) 
        at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java:463) 
        at io.grpc.internal.DelayedClientCall$DelayedListener.delayOrExecute(DelayedClientCall.java:427) 
        at io.grpc.internal.DelayedClientCall$DelayedListener.onClose(DelayedClientCall.java:460) 
        at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:557) 
        at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:69) 
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:738) 
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:717) 
        at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) 
        at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133) 
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462) 
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:234) 
        at java.lang.Thread.run(Thread.java:919)

 

데이터 보안

웹, Android 또는 Apple 플랫폼 SDK를 사용하는 경우 Firebase 인증  Cloud Firestore 보안 규칙을 사용하여 Cloud Firestore의 데이터에 보안을 적용한다.

다음은 시작하는 데 사용할 수 있는 기본 규칙 세트이다. Console의 규칙 탭에서 보안 규칙을 수정할 수 있다.

// Allow read/write access on all documents to any user signed in to the application
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

웹, Android 또는 iOS 앱을 프로덕션에 배포하기 전에 앱 클라이언트만 Cloud Firestore 데이터에 액세스할 수 있도록 하는 단계를 수행해야한다. 앱 체크 문서를 참조하자.

서버 SDK 중 하나를 사용하는 경우 Identity and Access Management(IAM)를 사용하여 Cloud Firestore의 데이터를 보호한다.

 

 

파이어베이스 콘솔에 로그인하여 나의 규칙탭을 확인해보니 다음과 같은 잠금모드였다.

// Deny read/write access to all users under any conditions
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

 

인증없이 아래와 같이 규칙을 테스트모드로 하면 바로 확인이 가능하고 오류도 사라졌다.

// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

 

[확인결과]

파이어베이스 콘솔 데이텁에서 확인결과 새로운 문서로 추가되었다.


안드로이드 스튜디오에서 로그창 확인결과  해당 문서 id를 리턴 받을 수 있다.


실제 마켓에 등록할때는 인증 규칙으로 변경 후 인증을 요구하면 될 것 같다.

 

 

[참고 코드]

 

 

 

Leave a Reply

error: Content is protected !!