인증

권한을 어디에서 확인해야 합니까?

권한을 확인할 위치를 결정할 때 여러 레이어에서 여러 체크를 구현하여 방어의 깊이를 적용하세요.

먼저, 파인더 및 서비스와 같은 저수준 레이어에서 시작하고,

GraphQL, 공용 REST API 및 컨트롤러와 같은 고수준 레이어가 이어집니다.

자세한 내용은 추상 재사용을 위한 지침을 참조하세요.

동일한 리소스를 여러 지점에서 보호하는 것은 한 레이어의 방어가 타협되거나 누락되더라도 고객 데이터가 추가 레이어에 의해 여전히 보호됨을 의미합니다.

권한에 대한 더 많은 정보는 보안 코딩 지침의 권한 섹션을 참조하세요.

고려 사항

서비스 또는 파인더는 적합한 위치입니다. 그 이유는:

  • 여러 엔드포인트가 서비스 또는 파인더를 공유하므로 하위 로직이 더 많이 재사용될 가능성이 높습니다.

  • 때때로 데이터베이스 쿼리에서 레코드를 필터링하기 위해 권한 로직을 통합해야 합니다.

  • 사용자 경험을 개선하기 위해서만 디스플레이 레이어에서 권한 체크를 피해야 하며, 보안 체크로 사용해서는 안 됩니다. 예를 들어 버튼과 같은 비 데이터 요소를 표시하거나 숨기는 경우입니다.

방어의 깊이에 대한 단점은 다음과 같습니다:

  • DeclarativePolicy 규칙은 상대적으로 성능이 좋지만, 조건이 데이터베이스 호출을 수행할 수 있습니다.

  • 유지 관리 비용이 더 높습니다.

예외

개발자는 특정 사례에 대한 위험과 단점을 저울질한 후 단일 영역에서만 권한 부여를 수행하도록 선택할 수 있습니다.

예외를 만들 때는 도메인 로직(서비스 또는 파인더)을 사실의 출처로 선호해야 합니다.

백엔드 작업 로직과 같은 로직은 현재 사용자에 대한 권한이 필요하지 않을 수 있습니다.

서비스 또는 파인더의 생성자가 current_user를 예상하지 않으면 일반적으로 권한을 확인하지 않습니다.

프론트엔드

UI 요소에서 능력 체크를 사용할 때는, 반드시 백엔드 코드의 기초에도 능력 체크를 사용해야 합니다.

이렇게 하면 사용자가 적절한 접근 권한을 갖기 전까지 기능을 사용할 수 있는 방법이 전혀 없도록 보장합니다.

UI 요소가 HAML인 경우, 다음과 같이 임베디드 루비를 사용하여 Ability.allowed?(user, action, subject)를 체크할 수 있습니다.

UI 요소가 JavaScript 또는 Vue인 경우, ApplicationController에서 상속되는 모든 컨트롤러에서 사용할 수 있는 push_frontend_ability 메소드를 사용하세요.

예를 들어, 다음과 같이 능력을 노출할 수 있습니다:

before_action do
  push_frontend_ability(ability: :read_project, resource: @project, user: current_user)
end

그런 다음 JavaScript에서 능력의 상태를 다음과 같이 확인할 수 있습니다:

if ( gon.abilities.readProject ) {
  // ...
}

JavaScript에서 능력의 이름은 항상 camelCase이므로, gon.abilities.read_project를 확인하면 작동하지 않습니다.

Vue 템플릿에서 능력을 확인하려면, Vue에서 접근 능력에 대한 개발자 문서를 참조하세요.

클래스가 current_user를 수용하면 권한 부여에 대한 책임이 있을 수 있습니다.

예: 새로운 API 엔드포인트 추가

기본적으로 우리는 엔드포인트에서 권한을 부여합니다. 기존의 능력을 확인하는 것이 의미가 있을 수 있습니다. 그렇지 않다면, 아마도 하나를 추가해야 합니다.

덧붙여 말하자면, 대부분의 엔드포인트는 리소스에 대한 CRUD(생성, 읽기, 업데이트, 삭제) 동작으로 깔끔하게 분류될 수 있습니다.

서비스와 능력도 따라서, 그래서 많은 이름이 Projects::CreateService 또는 :read_project와 같이 지어집니다.

예를 들어, 전체 엔드포인트를 서비스로 추출한다고 가정해 보겠습니다.

can? 체크는 이제 서비스에 있을 것입니다. 서비스가 우리 목적을 위해 수정하고 있는 기존 파인더를 재사용한다고 가정해 보겠습니다.

파인더가 능력을 확인해야 할까요?

  • 파인더가 current_user를 수용하지 않고 권한을 체크하지 않으면, 아마도 아닙니다.

  • 파인더가 current_user를 수용하고 권한을 체크하지 않으면, 파인더의 다른 사용을 다시 확인해야 하며, 권한 부여를 추가하는 것을 고려할 수 있습니다.

  • 파인더가 current_user를 수용하고 이미 권한을 체크하고 있다면, 우리의 경우를 추가해야 하거나 기존 체크가 적절합니다.