【问题标题】:Store/assign roles of authenticated users存储/分配经过身份验证的用户的角色
【发布时间】:2010-12-21 19:23:23
【问题描述】:

我正在升级一个站点以使用 MVC,并且我正在寻找设置身份验证的最佳方法。

此时,我已从 Active Directory 登录:验证用户名和密码,然后设置 Auth cookie。

如何在登录时存储用户的角色信息,以便我的控制器在用户浏览网站时看到这些角色?

[Authorize(Roles = "admin")]

我从 Active Directory 获取角色列表没有问题。我只是不知道把它们放在哪里,以便控制器看到它们。

【问题讨论】:

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


    【解决方案1】:

    角色被添加到 HttpContext 的IPrincipal。您可以创建一个GenericPrincipal,在构造函数中解析角色列表并将其设置为HttpContext.User。然后可以通过 User.IsInRole("role")[Authorize(Roles="role")] 属性访问 GenericPrincipal

    执行此操作的一种方法(在 C# 中)是在创建身份验证票证时将您的角色作为逗号分隔的字符串添加到用户数据参数中

    string roles = "Admin,Member";
    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
      1,
      userId,  //user id
      DateTime.Now,
      DateTime.Now.AddMinutes(20),  // expiry
      false,  //do not remember
      roles, 
      "/");
    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
                                       FormsAuthentication.Encrypt(authTicket));
    Response.Cookies.Add(cookie);
    

    然后从身份验证票证访问角色列表并从您的 Global.asax.cs 创建一个 GenericPrincipal

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

    【讨论】:

    • 如果克劳斯在你之前没有回答好,我会给你正确的答案。这也是我做事的确切方式。感谢您的详细回答。抱歉有点晚了。
    • @Omu 如果 cookie 不存在,您只需修改 Application_AuthenticationRequest() 方法以在 URL 中查找身份验证票证,即可支持无 cookie 身份验证。重要的部分是角色存储在加密的身份验证票中。
    • 如果您将角色存储在这样的cookie中,如果用户的角色被管理员或其他什么删除会发生什么?在 cookie 过期或清除 cookie 缓存之前,您不会看到此更新?
    • 每个请求(包括图片、css等)都会调用这个事件。是否要设置一个只添加一次角色的条件?
    • 我已经在 ASP.NET MVC 4 中对其进行了测试,我建议改用Application_PostAuthenticateRequest。否则通用主体将被覆盖。
    【解决方案2】:

    当您验证您的用户时,您会生成一个新的 GenericPrincipal 实例。构造函数接受一个字符串数组,这些字符串是用户的角色。现在设置 HttpContext.Current.User 等于通用主体并写入 auth cookie,就应该这样做。

    【讨论】:

      【解决方案3】:

      对于那些使用 MVC 4 或更高版本的人,在使用 David Glenn 的答案时,您需要听取 Jaroslaw Waliszko 的建议:

      “我已经在 ASP.NET MVC 4 中对其进行了测试,我建议改用 Application_PostAuthenticateRequest。否则通用主体将被覆盖。” – Jaroslaw Waliszko 9 月 7 日 16:18

      如上所述,您只需将 Application_AuthenticateRequest 方法名称替换为 Application_PostAuthenticateRequest 即可使其正常工作。对我来说就像一个魅力!如果允许我投票给 Jaroslaw 和 David,我会的。

      【讨论】:

      • 我试过了,但由于我是新注册的会员,我的 Stack Overflow 声誉不存在,所以我无法发表评论。如果这发生了,我会感到震惊和惊讶 :) 队列震惊和惊讶
      【解决方案4】:

      我倾向于只创建一个自定义角色提供程序。此处示例:

      http://www.danharman.net/2011/06/23/asp-net-mvc-3-custom-membership-provider-with-repository-injection/

      【讨论】:

        【解决方案5】:

        您能不能插入authorization store role managerfind (e.g. on Codeplex)write 另一个与Active Directory 一起使用以获取组信息的角色提供程序?

        这将为您省去验证用户、获取他们的角色、然后将该信息重新传递给构造函数的麻烦,并且所有这些都将作为框架的一部分自动为您完成。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-26
          • 1970-01-01
          • 2016-02-13
          • 1970-01-01
          • 2023-02-17
          • 2014-12-24
          • 1970-01-01
          相关资源
          最近更新 更多