2009-09-14 4 views
1

두 가지 매우 다른 유형의 사용자가있는 ASP.NET MVC를 사용하여 웹 응용 프로그램을 작성합니다. 예를 고안해보고 한 유형이 콘텐츠 제작자 (게시자)이고 다른 유형이 콘텐츠 소비자 (구독자)라고 말합니다.ASP.NET MVC 사용자 정의 승인

내 사용자 유형의 분리가 이분법이므로 게시자 또는 구독자이거나 둘 다 아니기 때문에 내장 된 ASP.NET 승인 항목을 사용할 계획이 아닙니다. 따라서 빌트인 인증은 필자가 필요로하는 것보다 훨씬 복잡합니다. 게다가 MySQL을 사용할 계획입니다.

열거 형 필드 (기술적으로 int 필드)를 사용하여 같은 테이블에 저장하려고 생각했습니다. 그런 다음 해당 페이지에 필요한 userType을 전달할 CustomAuthorizationAttribute를 만듭니다.

예를 들어 PublishContent 페이지에는 userType == UserType.Publisher가 필요하므로 게시자 만 액세스 할 수 있습니다. 따라서,이 속성을 생성하면 (IPrincipal 유형의) 표준 사용자 필드를 포함하는 HttpContextBase에 대한 액세스 권한이 부여됩니다. UserType 필드를이 IPrincipal에 어떻게 가져 옵니까? 그러면 내 속성은 다음과 같이 보입니다.

public class PublisherAuthorizationAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if (!httpContext.User.Identity.IsAuthenticated) 
      return false; 

     if (!httpContext.User.Identity.UserType == UserTypes.Publisher) 
      return false; 

     return true; 
    } 
} 

아니면 내 접근 방식에 결함이 있다고 생각합니까?

답변

3

나는 여전히 내장 된 ASP.NET 폼 인증을 사용하지만 필요에 맞게 사용자 정의합니다.

그래서 IPrincipal 인터페이스를 구현하고 사용자 정의 쿠키 처리를 작성하려면 User 클래스를 얻어야합니다. 그런 다음 [Authorize] 속성을 내장하여 사용할 수 있습니다.

가 현재 내를 Global.asax에서 다음과 유사한 ...

protected void Application_AuthenticateRequest() 
{ 
    HttpCookie cookie = Request.Cookies.Get(FormsAuthentication.FormsCookieName); 
    if (cookie == null) 
     return; 

    bool isPersistent; 
    int webuserid = GetUserId(cookie, out isPersistent); 

    //Lets see if the user exists 
    var webUserRepository = Kernel.Get<IWebUserRepository>(); 

    try 
    { 
     WebUser current = webUserRepository.GetById(webuserid); 

     //Refresh the cookie 
     var formsAuth = Kernel.Get<IFormsAuthService>(); 

     Response.Cookies.Add(formsAuth.GetAuthCookie(current, isPersistent)); 
     Context.User = current; 
    } 
    catch (Exception ex) 
    { 
     //TODO: Logging 
     RemoveAuthCookieAndRedirectToDefaultPage(); 
    } 
} 

private int GetUserId(HttpCookie cookie, out bool isPersistent) 
{ 
    try 
    { 
     FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); 
     isPersistent = ticket.IsPersistent; 
     return int.Parse(ticket.UserData); 
    } 
    catch (Exception ex) 
    { 
     //TODO: Logging 

     RemoveAuthCookieAndRedirectToDefaultPage(); 
     isPersistent = false; 
     return -1; 
    } 
} 

AccountController.cs

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult LogOn(LogOnForm logOnForm) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      WebUser user = AccountService.GetWebUserFromLogOnForm(logOnForm); 

      Response.Cookies.Add(FormsAuth.GetAuthCookie(user, logOnForm.RememberMe)); 

      return Redirect(logOnForm.ReturnUrl); 
     } 
    } 
    catch (ServiceLayerException ex) 
    { 
     ex.BindToModelState(ModelState); 
    } 
    catch 
    { 
     ModelState.AddModelError("*", "There was server error trying to log on, try again. If your problem persists, please contact us."); 
    } 

    return View("LogOn", logOnForm); 
} 

그리고 마지막으로 내 FormsAuthService :

public HttpCookie GetAuthCookie(WebUser webUser, bool createPersistentCookie) 
{ 
    var ticket = new FormsAuthenticationTicket(1, 
               webUser.Email, 
               DateTime.Now, 
               DateTime.Now.AddMonths(1), 
               createPersistentCookie, 
               webUser.Id.ToString()); 

    string cookieValue = FormsAuthentication.Encrypt(ticket); 

    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue) 
         { 
          Path = "/" 
         }; 

    if (createPersistentCookie) 
     authCookie.Expires = ticket.Expiration; 

    return authCookie; 
} 

HTHs
찰스

+0

이것은 MVC에서 테스트 할 수없는 난제를 만들 것입니다. 확실히 올바른 접근 방식은 아닙니다. –

+1

Untestable 엉망? 거의. 그것은 매우 짧게 보입니다. 'AccountService'와'FormsAuth' 서비스는 모두'AccountController'에 주입되는 인터페이스입니다 - 완전히 테스트 가능합니다. 다른 모든 것은 FormsAuthentication에 의존합니다 (formauth를 수행하는 다른 방법은 무엇입니까?). 기본 ASP.NET MVC 프로젝트가 지적한 것처럼, 알아야 할 것은 테스트하기가 어렵습니다. 물론 FormsAuthentication을 호출하여 서비스로 호출 할 수는 있지만 그 호출이 어디에 있는지 고려하면 실제로 달성 할 수있는 것은 무엇입니까? – Charlino

관련 문제