사용자 권한 검사는 어디서 그리고 MVC에서 누가해야합니까?


26

모델 또는 컨트롤러에서 사용자 권한 검사를 수행해야합니까? 그리고 누가 권한 확인, 사용자 개체 또는 일부 UserManagement 도우미를 처리해야합니까?

어디서 일어날까요?

컨트롤러 체크인 :

class MyController {
  void performSomeAction() {
    if (user.hasRightPermissions()) {
      model.someAction();
    }
  }
  ...

컨트롤러에서 검사를하면 모델을 간단한 동작으로 만드는 데 도움이되므로 컨트롤러에 대한 모든 논리를 유지할 수 있습니다.

모델 체크인 :

class MyModel {
  void someAction() {
    if (user.hasRightPermissions()) {
      ...
    }
  }
  ...

검사를 모델에 넣음으로써 모델을 복잡하게 만들지 만 실수로 사용자가 컨트롤러에서 원하지 않는 일을 할 수 없도록합니다.

그리고 누가?

우리가 그 장소에 정착하면, 누가 수표를해야합니까? 사용자?

Class User {
  bool hasPermissions(int permissionMask) {
    ...
  }
  ...

그러나 실제로 액세스 할 수있는 것을 아는 것은 사용자의 책임이 아닙니다. 어쩌면 도우미 클래스일까요?

Class UserManagement {
  bool hasPermissions(User user, int permissionMask) {
    ...
  }
  ...

나는 하나의 질문에 하나의 질문을하는 것이 일반적이라는 것을 알고 있지만, 이것들은 함께 잘 대답 할 수 있다고 생각합니다.

답변:


20

평소처럼 "의존한다"

  • 권한 확인 기능 은 편리한 위치에 기능적으로 작동 합니다.
  • 그러나 기술적 인 질문을하는 경우 대답은 '검사를 수행하는 데 필요한 데이터를 소유 한 개체에 검사를 넣습니다'(아마도 컨트롤러) 일 수 있습니다.
  • 그러나 철학적 질문을하는 경우 다른 대답을 제안합니다. 사용자에게 수행이 허용되지 않은 작업을 표시하지 마십시오 .

따라서 후자의 경우 컨트롤러에서 권한 검사를 부울 속성으로 구현하고 해당 속성을 작업을 제어하는 ​​사용자 인터페이스의 버튼 또는 패널의 Visible 속성에 바인딩 할 수 있습니다.

사용자로서 내가 수행 할 수없는 작업에 대한 버튼을 보는 것은 실망 스럽습니다. 내가 재미에서 빠져있는 것처럼 느낀다.)


우리의 응용 프로그램은 컨트롤을 숨기지 않고 예외로 세 번째 시나리오를 구현합니다. 불행히도 모두 Winforms 코드 숨김에서 수행되므로 OP 질문과 실제로 관련이 없습니다.
Dave Nay

11
"내가 수행 할 수없는 행동에 대한 버튼을보고 실망" > 자신의 포스트 : 찬성 투표하는 것을 시도하십시오 -
로완 프리먼

5
사용자가 수행 할 수없는 작업에 대한 버튼을 단순히 숨기는 것만으로는 충분하지 않습니다. 서버는 모든 권한 요청을 확인해야합니다. 세 번째 글 머리 기호 항목은 "대체 답변"이 아니며 서버 측 권한을 확인하는 것 외에 수행해야 할 작업입니다.
Flimm

요청이 서버에 의해 처리된다면 @Flimm은 동의했다. 구체적인 질문은 컨트롤러 클래스에 관한 것이 었습니다
Steven A. Lowe

7

보안은 매우 중요한 문제이므로 여러 계층으로 구현해야합니다. 다음은 MVC의 예이지만이 개념은 다른 아키텍처 및 / 또는 패턴에 적용되므로 시행 지점을 식별하면됩니다.

어디서 일어날까요?

보기 에는 권한에 따라 일부 사용자에게 표시되거나 표시되지 않아야하는 UI 요소 (위젯, 단추, 메뉴 등)가 포함될 수 있습니다. 모든보기가이를 자체적으로 처리하기를 원하지 않기 때문에 이것은 보기 엔진 의 책임이 될 수 있습니다 . 귀하에게 권한을 부여하는 요소의 유형에 따라이 책임을 다른 곳으로 이동시켜야합니다. 예를 들어, 일부 항목이 표시되고 일부는 표시되지 않아야하는 메뉴를 생각해보십시오. 항목을 어딘가에 목록으로 구현하고 권한에 따라 해당 목록을 필터링 한 다음보기로 전달할 수 있습니다.

컨트롤러 는 요청에 응답하므로 사용자에게 조치를 실행할 권한이없는 경우 조치를 호출하기 전에 점검해야합니다. 책임을 제어기에 유지하는 대신 조치 호출자 로 이동하십시오 . 이것은 컨트롤러를 깨끗하게 유지하는 이점이 있으며 권한에 어떤 변화가있을 경우 컨트롤러를 통해 변경 사항을 적용 할 필요가 없습니다.

권한에 따라 리소스 가 표시됩니다. 데이터베이스 에서 모든 것을 가져오고 권한을 적용하지 않기 때문에 일반적으로 데이터베이스 수준 에서 수행 됩니다.

보시다시피, 승인하려는 대상에 따라이 작업을 수행해야하는 위치가 다릅니다. 보안 정책이 변경 될 때 응용 프로그램 코드를 변경하지 않고 쉽게 적용 할 수 있도록 가능한 한 눈에 잘 띄지 않는 것이 목표입니다. 권한 집합이 상당히 작고 자주 변경되지 않는 소규모 응용 프로그램에는 유효하지 않을 수 있습니다. 그러나 엔터프라이즈 응용 프로그램에서는 그 이야기가 상당히 다릅니다.

누가해야합니까?

분명히 모델이 아닙니다. 각 계층에는 권한을 처리하는 시행 지점이 있어야합니다. 위의 기울임 꼴 텍스트는 각 수준에 대해 가능한 시행 지점을 강조합니다.

XACML을 살펴보십시오 . 그대로 구현할 필요는 없지만 따라갈 수있는 몇 가지 지침을 제공합니다.


이것이 가장 좋은 대답입니다. 어떤 이유로 든 상위 및 기타는 컨트롤러와보기 또는보기와 모델의 차이점을 다루며 이는 OP가 요구하는 것이 아닙니다. 감사!
redFur

1

나는 다음과 같은 계획을 사용합니다. 대부분의 사용자 권한 확인은 두 가지 일반적인 경우로 나눌 수 있습니다.

  • 매개 변수를 확인하지 않고 사용자 역할에 따라 컨트롤러 작업에 대한 사용자 액세스
  • 특정 사용자와 특정 모델 간의 관계 또는 논리를 기반으로 모델에 대한 사용자 액세스.

속성을 확인하지 않고 컨트롤러 작업에 액세스하는 것은 일반적으로 MVC 프레임 워크에서 구현됩니다. 이것은 매우 간단합니다. 규칙을 정의하고 사용자에게 역할이 있습니다. 사용자에게 규칙에서 역할을 조회 할 수있는 권한이 있는지 확인하기 만하면됩니다.

특정 모델에 대한 사용자 액세스는 모델에서 정의해야합니다. 액터는 기본 사용자 클래스입니다. 고객, 판매자 또는 손님 일 수 있다고 가정하십시오.

interface ICheckAccess
{
    public function checkAccess(Actor $actor, $role);
}

class SomeModel implements ICheckAccess
{
    public function checkAccess(Actor $actor, $role)
    {
        // Your permissions logic can be as sophisticated as you want.
    }
}

이 논리를 모델에 배치하면 약간의 이익이 발생합니다. 액세스 확인 방법을 상속받을 수 있으며 추가 클래스를 만들 필요가 없으며 일반적인 OOP 이점을 사용할 수 있습니다.

다음으로 액세스 확인을 단순화하기 위해 단순성과 좋은 스타일을 위해 거의 항상 구현 된 몇 가지 가정을 가정합니다.

  • 일반적으로 컨트롤러는 일부 모델 클래스와 관련이 있습니다.
  • 액세스가 확인 된 작업은 단일 모델 ID를 매개 변수로 사용합니다.
  • 이 파라미터는 항상 기본 컨트롤러 클래스의 메소드에서 균일하게 액세스 할 수 있습니다.
  • id 액션이 취하는 모델에 대응하는 액션이 ​​컨트롤러에 배치됩니다.

이러한 가정을 통해 모델 ID를 사용하는 조치는 특정 모델 인스턴스와 연관 될 수 있습니다. 실제로 대부분의 작업은 위에서 설명한 가정에 맞게 쉽게 변환하고 이동할 수 있습니다.

그런 다음 일부 기본 추상 컨트롤러 클래스를 정의하고 상속해야합니다.

abstract class ModelController
{
    // Retrieve model from database using id from action parameter.
    public abstract function loadModel($id);

    // Returns rules for user role to pass to SomeModel::checkAccess()
    // Something like array('view' => 'viewer', 'delete' => 'owner', 'update' => 'owner')
    public abstract function modelRules();

    public abstract fucntion getIdParameter();

    public function filterModelAccess()
    {
        $id = $this->getIdParameter();
        if(!$this->checkModelAccess($id))
            throw new HttpException(403);
    }

    public function checkModelAccess($id)
    {
        $model = $this->loadModel($id);
        $actor = My::app()->getActor();
        $rules = $this->modelRules();
        $role = $rules[My::app()->getActionName()];
        return $model->chechAccess($actor, $role);
    }
}

메뉴를 구성하고 링크 표시 여부를 결정할 때 SomeController :: checkModelAccess ($ id) 메소드를 호출 할 수 있습니다.


PHP가 유감입니다.
George Sovetov

1

모형 뷰 모두

보기 에서-UI는 현재 사용자에게 제한된 UI 요소를 표시해서는 안되기 때문에

(예 : 적절한 권한이있는 사용자에게 '삭제'버튼이 표시되어야 함)

모델에서 -앱에 아마도 일종의 API가 있기 때문입니다. API는 권한도 확인해야하며 모델을 재사용 할 수 있습니다.

(예 : UI에 '삭제'버튼 'http : / server / API / DeleteEntry / 123'API 메소드가 동시에있는 경우


컨트롤러보다 모델을 선택한 이유는 무엇입니까?
Flimm

컨트롤러가 아닌보기, 모델링 및 왜 대부분의 시간이 수행되는지 확실하지 않습니다.
VP.

@VP 컨트롤러 (뷰에 부울-VAR을 통과 제외) 더 보여줄 전원 / 숨기기 UI 요소가 없습니다
jitbit

나는 컨트롤러 계층에서 모든 곳에서 일반적으로 수행되는 것을 모른다. 그래서 내가 궁금했다.
VP.

0

MVC는 프리젠 테이션 패턴입니다. 그러한 견해와 관리자는 프리젠 테이션과 관련된 책임 만 가져야합니다. 전문가 모드, 실험적인 UI 기능 또는 다른 디자인과 같은 일부 권한은 프레젠테이션에 적용됩니다. 그것들은 MVC 컨트롤러에 의해 처리 될 수 있습니다.

다른 많은 종류의 권한은 응용 프로그램의 여러 계층과 관련이 있습니다. 예를 들어 데이터 만 볼 수 있고 내용을 변경할 수없는 사용자를 원할 경우 :

  • 프리젠 테이션 레이어는 편집 기능을 숨겨야합니다
  • 어쨌든 편집 기능이 호출되면 (비즈니스 계층의 응용 프로그램 특정 부분이 아닌 도메인의 응용 프로그램 특정 부분-TrainEditor가 아닌 TrainEditor에 의해) 감지되고 예외가 발생할 수 있습니다.
  • 데이터 액세스 계층은 쓰기도 검사 할 수 있지만 비즈니스 계층에 대한 지식이 너무 많아서 더 좋은 아이디어가되기 위해서는 더 복잡한 종류의 권한이 필요합니다.

이 접근법에는 중복이 있습니다. 그러나 프리젠 테이션이 일반적으로 일시적이기 때문에 프리젠 테이션 레이어가 의도 한대로 작동하는 경우 중복 검사를 의미하더라도 일반적으로 애플리케이션의보다 안정적인 부분에서 권한을 확인하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.