【问题标题】:HttpContext.Current.User != HttpContext.User?HttpContext.Current.User != HttpContext.User?
【发布时间】:2013-05-17 13:55:27
【问题描述】:

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

下面的代码显示了正在发生的事情。当用户登录时,这两个断言都会被命中,首先是全局 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

【问题讨论】:

  • 我已经扩展了我的答案,包括关于为什么会发生这种情况的评论,以及一个插图,希望对您有所帮助。如果您真的必须使用它而不是WebSecurity,请尝试Application_OnPostAuthenticateRequest

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


【解决方案1】:

您的问题标签上写着“aspnet-mvc (3 and 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 属性等效性的原始问题。

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 期间被覆盖(例如被RoleManagerModule)和(例如)变成RolePrincipal。然后可以推迟回数据库(再次取决于提供者)来获取角色,因此覆盖您的角色。如果你在Application_OnPostAuthenticateRequest 工作,你可能会没事的。

【讨论】:

  • 非常感谢 - 更改为使用 PostAuthenticateRequest 意味着我可以在控制器中看到我的角色。但也感谢有关 SimpleMembershipProvider 的提醒,我正在使用 MVC4,所以我可能会考虑使用它 - 无论是在这个项目中还是在未来
  • @SeanMill。也可以see my answer here 了解有关 SimpleMembership 如何联系在一起的更多信息。
  • +1, `protected void Application_OnPostAuthenticateRequest()` 已修复,我在Application_AuthenticateRequest 中遇到的有关角色的问题已得到解决。事件的简单变化使世界变得不同。谢谢
猜你喜欢
  • 1970-01-01
  • 2013-11-08
  • 2021-10-12
  • 2017-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多