HttpContext.Current.User!= HttpContext.User?

时间:2013-05-22 13:26:21

标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 forms-authentication

全局asax中的 HttpContext.Current.User 与动作方法中的 HttpContext.User 不一样吗?我为用户分配了一些角色,但他们似乎迷路了。

下面的代码显示了正在发生的事情。当用户登录时,两个Asserts都会被点击,首先是全局的asax,然后是action方法。然而,他们给出了不同的结果。

首先:

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

1 个答案:

答案 0 :(得分:8)

您的问题标签上写着“aspnet-mvc(3和4)”,那么您是否可以选择使用以下方法让您的生活更轻松?如果您正在使用VS2012中的MVC 4 Internet应用程序模板中的Simple Membership,这将为您开箱即用):

CreateUserAndAccount的优点是也可以轻松设置UserProfile的属性,例如:

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

修改,我发现以上内容并未回答有关.User属性等效的原始问题。

Controller中的

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。根据{{​​1}},可以在RoleProvider期间覆盖(例如RoleManagerModule),并且(例如)将其转换为PostAuthenticateRequest。然后,这可以推迟回到数据库(再次取决于提供者)以获取角色,从而覆盖您的角色。如果您在RolePrincipal中完成工作,那么您可能没问题。