8

HttpContext.Current.User在全局asax中不一樣HttpContext.User在一個action方法中嗎?我爲用戶分配了一些角色,但他們似乎迷失了方向。HttpContext.Current.User!= HttpContext.User?

下面的代碼顯示了正在發生的事情。當用戶登錄時,兩個斷言都會被觸發,首先是全局asax,然後是操作方法。但他們給出了不同的結果。

第一本:

protected void Application_AuthenticateRequest(object sender, EventArgs e) 
{ 
    // ... omitted some code to check user is authenticated 
    FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity; 

    string[] roles = new string[] { "admin", "user" }; 

    HttpContext.Current.User = 
     new System.Security.Principal.GenericPrincipal(identity, roles); 

    Assert(HttpContext.User.IsInRole("admin")); 
} 

然後這在我的操作方法:

public ActionResult Index() 
{ 
    bool isAdmin = HttpContext.User.IsInRole("admin"); 

    Assert(isAdmin); // this fails, isAdmin is false 

    // ... 
} 

我用下面的資源

This SO answer

http://csharpdotnetfreak.blogspot.com/2009/02/formsauthentication-ticket-roles-aspnet.html

+0

我已經擴大了我的答案,包括關於爲什麼發生這種情況的評論,以及插圖,希望有所幫助。試試'Application_OnPostAuthenticateRequest',如果你真的必須使用這個而不是'WebSecurity' –

回答

8

你的問題標籤說「aspnet-mvc(3和4)」,那麼你有選擇使用以下內容來讓你的生活更輕鬆?如果您正在使用Simple Membership從VS2012的MVC 4 Internet公司的應用程序模板,這將只是工作開箱即用的你):

CreateUserAndAccount的優點是很容易設置的用戶配置屬性爲好,例如:

WebSecurity.CreateUserAndAccount(newUser.UserName, newUser.Password, 
    new { FullName = newUser.FullName, Email = newUser.Email, Timezone = newUser.TZ }); 
Roles.AddUserToRoles(newUser.UserName, new[] {"admin", "user"}); 

編輯,我意識到上述方法不回答你原來的問題有關.User財產等值。

HttpContext在控制器是屬性:Controller.HttpContext。 global.asax.cs中的HttpContext是靜態類,所以這就是爲什麼您使用HttpContext.Current。他們指的是同樣的事情。

如果您運行以下代碼,您可以看到它們顯然是「相同的主體」。所以問題是你分配的角色發生了什麼?

protected void Application_AuthenticateRequest(object sender, EventArgs e) { 
    ... 
    FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity; 
    string[] roles = new string[] { "admin", "user" }; 
    identity.Label = "test label"; 
    System.Security.Principal.GenericPrincipal ppl = new System.Security.Principal.GenericPrincipal(identity, roles);    
    HttpContext.Current.User = ppl; 
... } 

public ActionResult Index() { 
    bool isAdmin = HttpContext.User.IsInRole("admin"); 
    bool isAdmin2 = System.Web.HttpContext.Current.User.IsInRole("admin"); 
    System.Web.Security.FormsIdentity identity = (System.Web.Security.FormsIdentity)HttpContext.User.Identity; 

    // The label is carried through from Application_AuthenticateRequest to Index. 
    string label = identity.Label; 
} 

的問題是,你分配一個GenericPrincipal.User。根據RoleProvider,這可以在PostAuthenticateRequest和(例如)變成RolePrincipal期間被覆蓋(例如由RoleManagerModule)。然後,這可以推遲到數據庫(再次取決於提供者)來獲取角色,從而覆蓋角色。如果你在Application_OnPostAuthenticateRequest中完成這項工作,你可能會好起來的。

+0

美麗的感謝 - 改變使用PostAuthenticateRequest意味着我可以看到我在控制器中的角色。但也要感謝關於SimpleMembershipProvider的負責人,我正在使用MVC4,所以我可能會考慮使用它 - 無論是在此項目中還是在未來 –

+0

@SeanMill中。此外[請參閱我的答案](http://stackoverflow.com/a/16734651/1945631)瞭解更多關於SimpleMembership如何結合在一起的信息。 –

+0

+1,'保護無效Application_OnPostAuthenticateRequest()'固定和問題我一直有關於'Application_AuthenticateRequest'檢查角色。事件的簡單變化造就了一個不同的世界。謝謝 –

相關問題