Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

실시간 데이터베이스 규칙 언어의 핵심 구문 알아보기

Firebase 실시간 데이터베이스 보안 규칙을 사용하면 데이터베이스에 저장된 데이터에 대한 액세스를 제어할 수 있습니다. 유연한 규칙 구문을 사용하면 데이터베이스에 대한 모든 쓰기에서 개별 노드에 대한 작업에 이르기까지 모든 것과 일치하는 규칙을 생성할 수 있습니다.

실시간 데이터베이스 보안 규칙 데이터베이스에 대한 선언적 구성이다. 이는 규칙이 제품 논리와 별도로 정의됨을 의미합니다. 여기에는 여러 가지 장점이 있습니다. 클라이언트는 보안을 적용할 책임이 없고 버그가 있는 구현은 데이터를 손상시키지 않으며 아마도 가장 중요한 것은 서버와 같은 중간 심판이 세상으로부터 데이터를 보호할 필요가 없다는 것입니다.

이 항목에서는 전체 규칙 집합을 만드는 데 사용되는 실시간 데이터베이스 보안 규칙의 기본 구문과 구조에 대해 설명합니다.

보안 규칙 구조화

실시간 데이터베이스 보안 규칙은 JSON 문서에 포함된 JavaScript와 유사한 표현식으로 구성됩니다. 규칙의 구조는 데이터베이스에 저장한 데이터의 구조를 따라야 합니다.

기본 규칙은, 노드의 집합 확보에 대한 액세스가 하나의 허용 또는 거부되고있는 액세스 (예를 들어, 읽기, 쓰기) 참여 방법조건을 식별합니다. 다음 예에서, 우리의 조건은 간단합니다 truefalse 진술하지만 다음 주제에 우리는 조건을 표현하는 역동적 인의 방법을 다룰 것이다.

우리가 확보하려고하는 경우에 따라서, 예를 들어, child_node 아래에있는 A parent_node , 추적에 대한 일반 구문은 다음과 같습니다

{
  "rules": {
    "parent_node": {
      "child_node": {
        ".read": <condition>,
        ".write": <condition>,
        ".validate": <condition>,
      }
    }
  }
}

이 패턴을 적용해봅시다. 예를 들어 메시지 목록을 추적하고 다음과 같은 데이터가 있다고 가정해 보겠습니다.

{
  "messages": {
    "message0": {
      "content": "Hello",
      "timestamp": 1405704370369
    },
    "message1": {
      "content": "Goodbye",
      "timestamp": 1405704395231
    },
    ...
  }
}

규칙도 비슷한 방식으로 구성되어야 합니다. 다음은 이 데이터 구조에 적합할 수 있는 읽기 전용 보안에 대한 일련의 규칙입니다. 이 예는 규칙이 적용되는 데이터베이스 노드와 해당 노드에서 규칙을 평가하기 위한 조건을 지정하는 방법을 보여줍니다.

{
  "rules": {
    // For requests to access the 'messages' node...
    "messages": {
      // ...and the individual wildcarded 'message' nodes beneath
      // (we'll cover wildcarding variables more a bit later)....
      "$message": {

        // For each message, allow a read operation if <condition>. In this
        // case, we specify our condition as "true", so read access is always granted.
        ".read": "true",

        // For read-only behavior, we specify that for write operations, our
        // condition is false.
        ".write": "false"
      }
    }
  }
}

기본 규칙 작업

: 데이터에 대해 수행되는 작업의 유형에 따라 보안을 적용하기위한 규칙의 세 가지 종류가 있습니다 .write , .read.validate . 다음은 목적을 간략하게 요약한 것입니다.

규칙 유형
.읽다 사용자가 데이터를 읽을 수 있는지 여부와 시기를 설명합니다.
.쓰다 데이터 쓰기가 허용되는지 여부와 시기를 설명합니다.
.확인 올바른 형식의 값이 어떻게 생겼는지, 자식 속성이 있는지 여부와 데이터 유형을 정의합니다.

와일드카드 캡처 변수

모든 규칙 문은 노드를 가리킵니다. 성명은 특정 노드를 가리 키거나 사용할 수있는 $ 계층 구조의 수준에서 노드의 세트 포인트에 와일드 카드 캡처 변수를. 이러한 캡처 변수를 사용하여 후속 규칙 문 내에서 사용할 노드 키 값을 저장합니다. 이 기술은 당신이, 우리는 다음 주제에서 자세히 다룰 것이다 뭔가를 더 복잡한 규칙 조건을 작성할 수 있습니다.

{
  "rules": {
    "rooms": {
      // this rule applies to any child of /rooms/, the key for each room id
      // is stored inside $room_id variable for reference
      "$room_id": {
        "topic": {
          // the room's topic can be changed if the room id has "public" in it
          ".write": "$room_id.contains('public')"
        }
      }
    }
  }
}

동적의 $ 변수는 일정 경로 이름과 병행하여 사용할 수있다. 이 예에서는 사용하고 $other 선언하는 변수를 .validate 규칙을 보장하는 widget 아닌 다른 아이가없는 titlecolor . 추가 자식이 생성되는 쓰기 작업은 실패합니다.

{
  "rules": {
    "widget": {
      // a widget can have a title or color attribute
      "title": { ".validate": true },
      "color": { ".validate": true },

      // but no other child paths are allowed
      // in this case, $other means any key excluding "title" and "color"
      "$other": { ".validate": false }
    }
  }
}

읽기 및 쓰기 규칙 캐스케이드

.read.write 규칙은 깊은 규칙을 무시 얕은 규칙, 하향식 (top-down)에서 작동합니다. 규칙 보조금이 특정 경로에서 읽거나 쓰기 권한이 있다면, 그것은 또한 그 아래의 모든 자식 노드에 대한 액세스 권한을 부여합니다. 다음 구조를 고려하십시오.

{
  "rules": {
     "foo": {
        // allows read to /foo/*
        ".read": "data.child('baz').val() === true",
        "bar": {
          /* ignored, since read was allowed already */
          ".read": false
        }
     }
  }
}

이 보안 구조는 허용 /bar/ 때마다 읽을 수 /foo/ 자식이 포함 baztrue . ".read": false 에서 규칙 /foo/bar/ 액세스가 자식 경로에 의해 취소 될 수 없기 때문에, 여기에 아무런 영향을 미치지 않습니다.

직관적이지 않은 것처럼 보일 수도 있지만 이것은 규칙 언어의 강력한 부분이며 최소한의 노력으로 매우 복잡한 액세스 권한을 구현할 수 있습니다. 이것은 이 가이드의 뒷부분에서 사용자 기반 보안에 대해 설명할 때 설명합니다.

참고 .validate 규칙이 계단식으로하지 않습니다. 쓰기가 허용되려면 모든 유효성 검사 규칙이 계층 구조의 모든 수준에서 충족되어야 합니다.

규칙은 필터가 아닙니다.

규칙은 원자적 방식으로 적용됩니다. 즉, 해당 위치나 상위 위치에 액세스 권한을 부여하는 규칙이 없으면 읽기 또는 쓰기 작업이 즉시 실패합니다. 영향을 받는 모든 하위 경로에 액세스할 수 있는 경우에도 상위 위치에서 읽기가 완전히 실패합니다. 다음 구조를 고려하십시오.

{
  "rules": {
    "records": {
      "rec1": {
        ".read": true
      },
      "rec2": {
        ".read": false
      }
    }
  }
}

규칙이 원자 적으로 평가하는 것을 이해하지 않으면, 그것은 가져 오는 것처럼 보일 수 /records/ 반환 경로를 rec1 아니라 rec2 . 그러나 실제 결과는 오류입니다.

자바스크립트
var db = firebase.database();
db.ref("records").once("value", function(snap) {
  // success method is not called
}, function(err) {
  // error callback triggered with PERMISSION_DENIED
});
오브젝티브-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[_ref child:@"records"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  // success block is not called
} withCancelBlock:^(NSError * _Nonnull error) {
  // cancel block triggered with PERMISSION_DENIED
}];
빠른
var ref = FIRDatabase.database().reference()
ref.child("records").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // success block is not called
}, withCancelBlock: { error in
    // cancel block triggered with PERMISSION_DENIED
})
자바
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // success method is not called
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback triggered with PERMISSION_DENIED
  });
});
쉬다
curl https://docs-examples.firebaseio.com/rest/records/
# response returns a PERMISSION_DENIED error

에서 읽기 동작 때문에 /records/ 원자이고, 아래에있는 모든 데이터에 대한 액세스 권한을 부여한다는 읽기 규칙이 없다 /records/ 이가 발생합니다 PERMISSION_DENIED 오류가. 우리는 우리의 보안 시뮬레이터에서이 규칙을 평가하는 경우 중포 기지 콘솔을 , 우리는 더 읽기 규칙은에 액세스 할 수 없기 때문에 읽기 작업이 거부 된 것을 볼 수 있습니다 /records/ 경로를. 그러나에 대한 규칙 참고 rec1 평가되지 않았다 우리가 요청한 경로에 없었기 때문에. 가져 rec1 , 우리는 직접 액세스해야합니다 :

자바스크립트
var db = firebase.database();
db.ref("records/rec1").once("value", function(snap) {
  // SUCCESS!
}, function(err) {
  // error callback is not called
});
오브젝티브-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
빠른
var ref = FIRDatabase.database().reference()
ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // SUCCESS!
})
자바
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records/rec1");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // SUCCESS!
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback is not called
  }
});
쉬다
curl https://docs-examples.firebaseio.com/rest/records/rec1
# SUCCESS!

겹치는 문

하나 이상의 규칙이 노드에 적용될 수 있습니다. 여러 규칙 식 노드를 식별하는 경우, 액세스 방법은 조건이있는 경우 거부 false :

{
  "rules": {
    "messages": {
      // A rule expression that applies to all nodes in the 'messages' node
      "$message": {
        ".read": "true",
        ".write": "true"
      },
      // A second rule expression applying specifically to the 'message1` node
      "message1": {
        ".read": "false",
        ".write": "false"
      }
    }
  }
}

위의 예에서 읽 message1 두 번째 규칙은 항상 있기 때문에 거부됩니다 노드 false 첫 번째 규칙은 항상 경우에도 true .

다음 단계

Firebase 실시간 데이터베이스 보안 규칙에 대한 이해를 심화할 수 있습니다.

  • 규칙 언어, 동적의 다음 주요 개념을 알아 조건 , 규칙 체크 사용자 인증을하자, 기존 및 수신 데이터를 비교, 입력 데이터의 유효성을 검사, 클라이언트에서 오는 쿼리의 구조를 확인하고 더.

  • 일반적인 보안 사용 사례 및 검토 중포 기지 보안 규칙 정의 주소 그 것을 .