2011-03-29 4 views
11

현재 프로젝트와 관련하여 롤에 관련된 문제가 발생했으며 문제를 해결하는 방법에 대한 의견이 몇 가지 있습니다.MVC에서 다중 역할 처리 - 액션 기반 액세스 가능성

시스템은 특정 영역의 액세스뿐만 아니라 시스템 기능의 사용 (보고서 등보기, 사용자 편집, 사용자 추가)뿐만 아니라 제어 편집 가능한 유연한 역할이 필요합니다

시스템은 현재 사용자 수 여러 역할을 가지고, 그 각각의 역할을 명시 적으로 예를 들어, 액세스/작업 영역을 정의했습니다

  • 역할이 지역 1,2,3 액세스 할 수 있으며 사용자를 추가 할 수 있습니다.
  • 역할 B은 1,5,7 영역에 액세스 할 수 있으며 사용자를 수정할 수 있습니다.
  • 역할 C은 영역 4,6에 액세스 할 수 있으며 사용자보기 만 가능합니다.

사용자가 역할 A와 C에있을 수 있으므로 액세스 : 1,2,3,4 및 6, 사용자 추가 및보기를 할 수 있습니다. 그것에서 모든 속성을 가져옵니다 인스턴스화 될 때 다음

Dictionary<string,bool> 

:

내 최초의 솔루션은 매우처럼 사전에 액세스/액세스 옵션의 가능한 모든 영역을 저장하는 것입니다 사전을 만드는 것이 었습니다 데이터베이스를 검색하고 역할을 반복하여 액세스 가능한지 판별하십시오.

현재 모두 잘 작동합니다. 그러나 프로젝트는 상당히 Javascript/jQuery를 많이 사용하므로 많은 옵션이 클라이언트 측 함수에 의해 호출됩니다. 나는 다음과 같은 것들에 대해 궁금 그래서 기본적으로

<%if(AccessDictionary[key]) 
    //Enable or Disable Action 
<%}%> 

: 나는 이러한 클라이언트 측의 모든 기능을 래핑하는 것을 피하기 위해 노력하고 사용자가 로그인 한 후

  1. , 무엇을 이 사전을 저장하는 가장 좋은 방법은 무엇입니까? 정적으로? 세션?
  2. 보기에서 사전에 쉽게 액세스 할 수있는 가장 좋은 저장 방법은 무엇입니까? (현재 클라이언트 측 기능을 래핑 할 방법이 없습니다.)

모든 조언이나 아이디어를 높이 평가하겠습니다!

+0

web.config의 위치 기반 권한 부여 보안 설정으로 제어 할 수 없습니까? – Holystream

답변

20

이 정보는 인증 쿠키의 사용자 데이터 부분에 저장됩니다. 그래서 사용자가 로그인 할 때 :

public ActionResult Login(string username, string password) 
{ 
    // TODO: validate username/password couple and 
    // if they are valid get the roles for the user 

    var roles = "RoleA|RoleC"; 
    var ticket = new FormsAuthenticationTicket(
     1, 
     username, 
     DateTime.Now, 
     DateTime.Now.AddMilliseconds(FormsAuthentication.Timeout.TotalMilliseconds), 
     false, 
     roles 
    ); 
    var encryptedTicket = FormsAuthentication.Encrypt(ticket); 
    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) 
    { 
     // IIRC this property is only available in .NET 4.0, 
     // so you might need a constant here to match the domain property 
     // in the <forms> tag of the web.config 
     Domain = FormsAuthentication.CookieDomain, 
     HttpOnly = true, 
     Secure = FormsAuthentication.RequireSSL, 
    }; 
    Response.AppendCookie(authCookie); 
    return RedirectToAction("SomeSecureAction"); 
} 

은 그 때 나는 독서를 돌봐 및 인증 티켓을 구문 분석하고있는 HttpContext에서 일반 사용자를 저장하는 사용자 정의 authroize 속성을 작성합니다.이에 대응하는 역할을 가지고있는 사용자 속성 :

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if (httpContext.User.Identity.IsAuthenticated) 
     { 
      var authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName]; 
      if (authCookie != null) 
      { 
       var ticket = FormsAuthentication.Decrypt(authCookie.Value); 
       var roles = ticket.UserData.Split('|'); 
       var identity = new GenericIdentity(ticket.Name); 
       httpContext.User = new GenericPrincipal(identity, roles); 
      } 
     } 
     return base.AuthorizeCore(httpContext); 
    } 
} 

다음 당신은 당신의 컨트롤러를 장식 할 수 /이 속성과 행동을 처리 할 수있는 권한 :

사용자가 단순히 주어진 역할에 있는지 여부를 확인하기 위해
// Only users that have RoleA or RoleB can access this action 
// Note that this works only with OR => that's how the base 
// authorize attribute is implemented. If you need to handle AND 
// you will need to completely short-circuit the base method call 
// in your custom authroize attribute and simply handle this 
// case manually 
[MyAuthorize(Roles = "RoleA,RoleB")] 
public ActionResult Foo() 
{ 
    ... 
} 

:

bool isInRole = User.IsInRole("RoleC"); 

이 정보로 무장 한 이제보기 모델을 구성하는 방법에 대해 생각할 수 있습니다. 이러한 뷰 모델에는 CanEdit, CanViewReport 등과 같은 부울 속성이 포함됩니다. 컨트롤러에 의해 채워집니다.

이제 각 동작 및보기에서이 매핑이 필요할 경우 반복적이고 지루할 수 있습니다. 이것은 글로벌 사용자 지정 작업 필터가 작동하는 곳입니다 (ASP.NET MVC 2에만 존재하지는 않지만 ASP.NET MVC 3에만 존재하므로이 동작 필터로 장식 된 기본 컨트롤러가 필요함) 기능). 당신은 단순히 각각의 액션 후에 실행되는 글로벌 액션 필터를 정의하고 ViewData (holy ...., 나는 그 단어들을 발음하고 있다고 믿을 수 없다)에 대한 몇 가지 공통 뷰 모델을 주입하여, 그것들을 transverse의 모든 뷰에서 사용할 수있게 만든다. 다른 행동 방식.

마지막으로보기에서 해당 부울 값 속성을 확인하여 사이트의 다른 영역을 포함하거나 포함하지 않을 것입니다. 지금까지 자바 스크립트 코드가 중요하지 않은 경우 사이트의 영역을 조심스럽게 AJAX 화하면 해당 영역이 DOM에없는 경우이 코드는 실행되지 않습니다. 더 세분화 된 제어가 필요한 경우 항상 HTML5 data-* 속성을 DOM 요소에 사용하여 사용자의 권한에 대한 외부 자바 스크립트 기능에 대한 힌트를 제공 할 수 있습니다.

+0

평소 Darin처럼 심오한 답변을 보내 주셔서 감사합니다. 이런 식으로 통합하는 방법을 살펴 보겠습니다. 또한 - 나는 "거룩한 ...."ViewData 언급에 대해 또 하나의 +1을 줄 것입니다. :) –

+0

사용자 역할과 같은 중요한 정보를 쿠키에 저장하려면 최신 .NET 패치가 모두 있어야합니다. 이전에는 FormsAuthentication.Encypt()에 취약점이있었습니다. – Ryan

+0

또한 data- * 아이디어가 정말 좋습니다. – Ryan