2009-09-14 135 views
1

我正在構建一個使用ASP.NET MVC的Web應用程序,它有兩種非常不同類型的用戶。我將舉一個例子,說一種類型是內容製作者(發佈者),另一種是內容消費者(訂閱者)。ASP.NET MVC定製授權

我不打算使用內置的ASP.NET授權的東西,因爲我的用戶類型的分離是一個二分法,你要麼出版商或用戶,不能同時使用。所以,內置授權比我需要的更復雜。另外我正在計劃使用MySQL。

我想在同一個表中存儲他們的枚舉場(技術上一個int字段)。然後創建一個CustomAuthorizationAttribute,在那裏我傳入該頁面所需的userType。

例如,PublishContent頁面會要求用戶類型== UserType.Publisher,所以只有出版商可以訪問它。因此,創建此屬性使我可以訪問HttpContextBase,其中包含標準User字段(IPrincipal類型)。如何將我的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接口,然後寫自己的自定義cookie處理。然後你可以簡單地使用內置的[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一個無法驗證的混亂。絕對不是正確的做法。 – 2010-01-20 05:00:35

+1

無法檢測的混亂?幾乎不。這是非常短暫的說。 'AccountService'和'FormsAuth'服務都是注入到'AccountController'中的接口 - 使得它們完全可以測試。正如你應該知道的,其他所有的東西都依賴於FormsAuthentication(你還怎麼做formauth?),正如默認的ASP.NET MVC項目所指出的那樣,它是非常難以測試的。當然,你可以將FormsAuthentication調用提取出來,但是真正要實現的方式是考慮調用它的位置是什麼? – Charlino 2010-01-20 08:22:22