5

ASP.NET MVC의 사용자 및 역할 기반 보안에 대해 이미 알고 있습니다. 하지만 이제 좀 더 세분화 된 것이 필요합니다.ASP.NET MVC의 문서 기반 보안

문서의 목록이 있다고 가정 해 봅시다. 일부는 사용자에게 권한이 부여되고 일부는 승인되지 않습니다. 각. 서에는 데이터베이스의. 서 테이블에 해당 레코드가 있습니다. 사용자가 보안 액세스 권한을 가진 경우 문서를 다운로드하여 볼 수 있습니다. 역할이있는 경우 문서를 추가 할 수도 있습니다. 각 문서에는 URL이 있고 각 문서 목록에는 URL이 있습니다.

사용자가 권한이있는 문서 만 볼 수 있도록 목록을 보안 정리하고 싶습니다. 그러나 사용자가 더 이상 액세스 할 수없는 문서를 북 마킹하거나 단순히 URL을 브라우저에 입력하는 것을 방지 할 수있는 것이 없기 때문에 이러한 목록 및 문서에 대한 URL 요청을 인증해야합니다.

기본 제공 역할 기반 보안 모델이 이에 적합합니까? 아니면 별도의 테이블 기반 보안을 만들어야합니까? 리포지토리에 보안을 적용하여 반환 된 레코드가 이미 다듬어 졌거나 컨트롤러에 포함되어 있어야합니까? 컨트롤러 요청의 유효성을 검사하기 위해 보안 속성이 필요합니까? 아니면 코드의 처음 몇 줄과 같이 컨트롤러 메서드에 넣어야합니까?

답변

1

@ 로버트, 나는 당신이 이미보기에 도달하기 전에 (전에) 자신을 정리해야한다고 말했을 때 이미 자신의 질문에 대답했다고 생각합니다. 따라서 비즈니스 논리에서 저장소에 대한 선호도로서, 초과 작업을 말하기 위해 램다 (lamda)를 수행하는 것이 좋습니다.

내 의견 필자는 사용자가 볼 수없는보기에 어떤 레코드도 반환하지 않을 것입니다. 위험과 트래픽을 증가시키는 이유는 무엇입니까?

북마크에 관해서는 액세스가 더 이상 존재하지 않을 때 URL로 이동하지 못하게하는 비즈니스 로직이 필요하다고 생각합니다.

저는 컨트롤러가 단순히 데이터를 페이지에 제공하고 로직을 갖고 있지 않으므로 비즈니스 규칙으로 보이는 것처럼 비즈니스 계층 접근 방식을 선호한다고 생각했습니다.

당신이 염두에 두지 않았을 수도 있지만, 더 나은 접근법이 없다면 그것은 내가 사용할 것입니다.

+0

DAL/ORM의 부분 클래스에 상주하는 비즈니스 로직을 사용하는 방식을 선호하는 것 같습니다. 그게 옳은 것 같니? –

+0

그래도 그보다는 더 뚜렷 하긴하지만. DAL에서 부분적으로 생각한다는 점을 염두에두고 생각했지만, 필자가 선호하는 방식은 항상 실제 비즈니스 계층에이를 적용하는 것이 었습니다. 물론이 레이어는 DAL 개체를 참조하지만 내 데이터베이스에서 비즈니스 로직을 분리합니다. 액세스 권리가 DAL 관심사가 아닌 비즈니스 규칙 인 것처럼 들립니다. – griegs

+0

나는 그것을 비즈니스 논리에 넣는 아이디어를 좋아한다. 컨트롤러에서 보안 검사를 숨기고 보안 트리밍 작업을 한 번 수행하면됩니다. –

1

저는 이것을 프로젝트에서 어떻게 구현할 것인지 설명하려고합니다. 요구 사항은 귀하의 권한과 유사합니다 : 사용자는 권한이있는 역할을 가지며 권한 정의, 역할의 권한 목록 및 사용자 역할 목록 등에서 모든 것이 바뀔 수 있습니다. 관리자가 다음과 같이 변경할 수 있습니다. 뭔가, 그는 접근 할 수 없다.

몇 가지 코드를 작성하기 전에 질문에 답변 해 드리겠습니다.

별도의 테이블 기반 보안을 만들어야합니까? 반환 된 기록이 이미립니다, 또는 컨트롤러의 일부가 될 한다 있도록

나는, 내 저장소에 보안을 할 수 있나요?

- 저는 보안이 비즈니스 로직의 일부가되어야한다고 생각합니다. 컨트롤러와 저장소 사이 어딘가에 넣을 것입니다.

컨트롤러 요청의 유효성을 검사하려면 보안 속성이 필요합니까?

- 내 프로젝트에서는 속성에 넣었지만 때로는 컨트롤러에서 액세스해야하지만 보안 계층을 비즈니스 계층에 보관해야하므로 문제가 아닌 것 같습니다. .

첫 번째 속성은 로그인 한 사용자가 실행할 수 있도록 간단한 속성입니다 조치 :

public class LoggedUserFilterAttribute : ActionFilterAttribute 
{ 
    public bool Logged { get; set; } 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (!SessionManager.IsUserLogged) 
     { 
      filterContext.Result = new RedirectToRouteResult(GetRedirectToNotLoggedRouteValues()); 
      this.Logged = false; 
     } 
     else 
      this.Logged = true; 
    } 

    public RouteValueDictionary GetRedirectToNotAuthorizedRouteValues() 
    { 
     RouteValueDictionary routeValues = new RouteValueDictionary(); 
     routeValues.Add("action", "NotAuthorized"); 
     routeValues.Add("controller", "Authorization"); 
     return routeValues; 
    } 
    public RouteValueDictionary GetRedirectToNotLoggedRouteValues() 
    { 
     RouteValueDictionary routeValues = new RouteValueDictionary(); 
     routeValues.Add("action", "NotLogged"); 
     routeValues.Add("controller", "Authorization"); 
     return routeValues; 
    } 
} 

하고 내가 가지고있는, 예를 들어, 수 속성이 슈퍼 유저 만이 액세스 할 수 :

public class SuperUserFilterAttribute : LoggedUserFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 

     if (Logged) 
     { 
      MyBaseController controller = filterContext.Controller as MyBaseController; 
      if (controller == null) 
       throw new Exception("Please use MyBaseController instead of built in Controller"); 

      User loggedUser = controller.Model.UserBO.GetUserByID(SessionManager.LoggedUser.UserID); 

      if(!loggedUser.IsSuperUser) 
      { 
       filterContext.Result = new RedirectToRouteResult(GetRedirectToNotAuthorizedRouteValues()); 
      } 
     } 
    } 
} 

MyBaseController는 Controller를 상속하는 클래스이며 Business Object의 컨테이너를 나타내는 Model 클래스의 인스턴스를가집니다. 컨트롤러 액션 본문에서 필요한 경우 현재 엔터티에 대한 사용자 권한을 확인하고 이에 따라 적절한보기를 반환합니다.

[LoggedUserFilter] 
    public ActionResult LoadSomeEntity(int customerServiceID,int entityID) 
    { 
     UserRights userPermissionsView = Model.SecurityBO.GetUsersRightsOnEntity(SessionManager.LoggedUser.UserID, entityID); 

     if(userPermissionsView.Write) 
      return View("EditEntity",Model.EntityBO.GetEntityByID(entityID)); 
     if(userPermissionsView.Read) 
      return View("ViewEntity",Model.EntityBO.GetEntityByID(entityID)); 

     return View("NotAuthorized");  
    } 

p.s. 나는 분명히 나에게 훨씬 더 많은 경험이있는 누군가에게 어떤 것을 제안 할 수 있는지 확신 할 수 없다. 스팸을 보내는 경우 사과한다.

+0

답장을 보내 주셔서 감사합니다. 당신은 올바른 생각을 가지고 있습니다. 사용자 및 역할 인증에 적용 할 때 속성 패턴을 보았습니다. 다른 사람이 테이블 기반 보안을 위해 Attributes를 사용하는 것에 대해 질문을 올리는 것을 보았습니다. 이 접근법의 문제점은 제대로 수행하기 위해 URL 매개 변수에 액세스해야한다는 것입니다. 속성은 컨트롤러 메소드의 매개 변수에 액세스 할 수 없기 때문에 이제는 그것을 얻기 위해 일부 농구를 뛰어 넘어야합니다. –

+0

OnAuthorize 메서드의 AuthorizeAttribute에 컨트롤러 메서드의 매개 변수에 대한 액세스 권한이 없지만 사용한 OnActionExecuting의 ActionFilterAttribute가 있습니다. IDictionary 를 반환하는 filterContext.ActionParameters 속성이 있습니다. 여기서 key는 매개 변수입니다. 이름과 값은 메서드에 전달 된 값입니다. –

+0

그건 좋은 관찰이지만, 그냥 내 취향에 너무 멀리 제거 된 것 같습니다. 어쨌든 내 모델에서 데이터를 가져올 것이므로 보안 기능 만 있으면됩니다. 사용자가 특정 레코드에 대한 액세스 권한이 없으면 목록에 표시되지 않고 단일 레코드가 상세보기로 검색되는 경우 null을 확인하고 리디렉션 할 수 있습니다. –