Как получить пользовательский поставщик ролей с пользовательским принципалом пользователя

Долгое время скрывался первый раз постер..

пытаясь реализовать простую пользовательскую роль и членство провайдера для MVC.

Реализовали классы провайдеров ролей и членства и подключили их к моему web.config. добавлен код для проверки моих пользователей по пользовательской базе данных, и он работает нормально.

Однако мне не нравится, как мой ролевой провайдер обращается к базе данных при каждом запросе, поэтому я добавил некоторый код, чтобы попытаться прочитать его из билета аутентификации следующим образом:

пользовательский поставщик ролей:

public override string[] GetRolesForUser(string username)
   {
       if (HttpContext.Current.User != null)
       {
           return ((UserPrincipal)HttpContext.Current.User).Roles.ToArray();
       }
       else
       {
           UserPrincipal user = orchestrator.GetUserByLoginID(username);
           return user.Roles.ToArray();
       }
   }

затем я добавил этот код в global.asax, чтобы сохранить роли и некоторую другую полезную информацию о пользователе в cookie-файле с помощью пользовательского основного объекта:

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
    {
        HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

        if (authCookie != null)
        {
            FormsAuthenticationTicket authTicket =      FormsAuthentication.Decrypt(authCookie.Value);

            JavaScriptSerializer serializer = new JavaScriptSerializer();

            UserPrincipalModel userFromTicket = serializer.Deserialize<UserPrincipalModel>(authTicket.UserData);

            UserPrincipal newUser = new UserPrincipal();
            newUser.UserId = userFromTicket.UserId;
            newUser.FullName = userFromTicket.Fullname;
            newUser.Email = userFromTicket.Email;
            newUser.Roles = userFromTicket.Roles;
            newUser.Identity = new GenericIdentity(userFromTicket.Username);

            HttpContext.Current.User = newUser;
        }
    }

мой основной класс пользователя:

  public class UserPrincipal : IPrincipal
{
    public UserPrincipal() { }
    public UserPrincipal(int userId, string userName, string fullName, string password)
    {
        UserId = userId;
        UserName = userName;
        FullName = fullName;
        Password = password;
    }
    public virtual int UserId { get; set; }
    public virtual string UserName { get; set; }
    public virtual string FullName { get; set; }
    public virtual string Email { get; set; }
    public virtual string Password { get; set; }        
    public virtual IEnumerable<string> Roles { get; set; }

    public virtual IIdentity Identity { get; set; }

    public virtual bool IsInRole(string role)
    {
        if (Roles.Contains(role))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

   //public string[] GetRolesForUser()
   //{
   //    return Roles;
   //}
}

Однако, когда я запускаю это, я получаю следующую ошибку, когда поставщик роли пытается получить доступ к пользовательскому объекту UserPrincipal в файле cookie.

"Невозможно привести объект типа" System.Web.Security.RolePrincipal "к типу" MyApp.Domain.UserPrincipal "".

Это похоже на то, что поставщик пользовательских ролей перезаписывает пользовательский принципал, сохраняемый в заявке, своим собственным принципалом, специфичным для роли.

Просто интересно, является ли то, что я пытаюсь сделать, ошибочным или есть более простой способ. Не хочу изобретать велосипед.

Кто-нибудь получил пример нестандартного поставщика ролей, который не попадает в базу данных при каждом запросе ролей?

1 ответ

Измените это прямо здесь:

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 

На это прямо здесь:

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)

По сути, внутренняя работа поставщика ролей по умолчанию устанавливает свойство HttpContext.Current.User после его установки, перезаписывая то, что вы сделали.

Вы также можете попытаться очистить поставщика роли по умолчанию, он работает в веб-формах mvc3 и asp.net, но не работает в mvc 4.

<membership>
  <providers>
    <clear />
  </providers>
</membership>
<profile>
  <providers>
    <clear />
  </providers>
</profile>
<roleManager enabled="false">
  <providers>
    <clear />
  </providers>
</roleManager>
Другие вопросы по тегам