2011-03-15 195 views
8

我發現了一個很好的回答在SO描述how to set up custom user roles,我在我的項目中也做了同樣的。所以在我的登錄服務,我有:用戶在角色「管理員」,但[授權(角色=「管理員」)]將不驗證

public ActionResult Login() { 
    // password authentication stuff omitted here 
    var roles = GetRoles(user.Type); // returns a string e.g. "admin,user" 
    var authTicket = new FormsAuthenticationTicket(
        1, 
        userName, 
        DateTime.Now, 
        DateTime.Now.AddMinutes(20), // expiry 
        false, 
        roles, 
        "/"); 
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, 
    FormsAuthentication.Encrypt(authTicket)); 
    Response.Cookies.Add(cookie); 
    return new XmlResult(xmlDoc); // don't worry so much about this - returns XML as ActionResult 
} 

而在Global.asax.cs中,我已經(從逐字其他答案複製):

protected void Application_AuthenticateRequest(Object sender, EventArgs e) { 
    var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; 
    if (authCookie != null) { 
    var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
    var roles = authTicket.UserData.Split(new Char[] { ',' }); 
    var userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles); 
    Context.User = userPrincipal; 
    } 
} 

然後,在我的ServicesController類,我有:

[Authorize(Roles = "admin")] 
//[Authorize] 
public ActionResult DoAdminStuff() { 
    ... 
} 

我以具有「管理員」角色的用戶身份登錄,並且工作正常。然後我調用/ services/doadminstuff - 即使在Global.asax.cs中放置斷點時,我也可以看到我的角色包含「admin」。如果我註釋掉第一個Authorize屬性(包含角色)並僅使用簡單的香草Authorize,那麼我可以訪問該服務。

我必須在這裏丟失重要的東西 - 但從哪裏開始尋找?

回答

15

我會建議你使用自定義的授權屬性,而不是Application_AuthenticateRequest

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     string cookieName = FormsAuthentication.FormsCookieName; 

     if (!filterContext.HttpContext.User.Identity.IsAuthenticated || 
      filterContext.HttpContext.Request.Cookies == null || 
      filterContext.HttpContext.Request.Cookies[cookieName] == null 
     ) 
     { 
      HandleUnauthorizedRequest(filterContext); 
      return; 
     } 

     var authCookie = filterContext.HttpContext.Request.Cookies[cookieName]; 
     var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
     string[] roles = authTicket.UserData.Split(','); 

     var userIdentity = new GenericIdentity(authTicket.Name); 
     var userPrincipal = new GenericPrincipal(userIdentity, roles); 

     filterContext.HttpContext.User = userPrincipal; 
     base.OnAuthorization(filterContext); 
    } 
} 

然後:

[CustomAuthorize(Roles = "admin")] 
public ActionResult DoAdminStuff() 
{ 
    ... 
} 

也是一個非常重要的事情是要確保當你登錄身份驗證Cookie是因爲你返回一個XML文件而發射。當您嘗試訪問url /services/doadminstuff時,使用FireBug檢查身份驗證Cookie是否已正確發送。

+3

它的工作!謝謝!告訴我,爲什麼這個工作,但Global.asax.cs中沒有? – 2011-03-15 16:32:05

+1

再次感謝您的幫助!也許你也可以解釋一下這個相關的問題:http://stackoverflow.com/q/6586156/7850 – 2011-07-05 16:57:01

+0

謝謝,它的工作原理。我怎樣才能進一步控制顯示哪個頁面和正確的消息。 – Timeless 2014-07-18 06:30:11

0

我將在第一個改變主要分配:

Thread.CurrentPrincipal = userPrincipal; 
if (HttpContext.Current != null) 
{ 
    HttpContext.Current.User = userPrincipal; 
} 

爲ASP.NET文件表示。

相關問題