2011-11-01 13 views
8

Tengo una aplicación MVC y escribí un RoleProvider personalizado para ello, como se muestra:MVC encargo RoleProvider cómo conectarlo a HttpContext.Current.User.IsInRole ("myrole")

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Security; 
using VectorCheck.Models; 

namespace VectorCheck.Security 
{ 
    public class MyRoleProvider : RoleProvider 
    { 
     private VectorCheckRepository<User> _repository { get; set; } 

     public MyRoleProvider() 
     { 
      _repository = new VectorCheckRepository<User>(); 
     } 

     public MyRoleProvider(VectorCheckRepository<User> repository) 
     { 
      _repository = repository; 
     } 

     public override void AddUsersToRoles(string[] usernames, string[] roleNames) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string ApplicationName 
     { 
      get 
      { 
       throw new NotImplementedException(); 
      } 
      set 
      { 
       throw new NotImplementedException(); 
      } 
     } 

     public override void CreateRole(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string[] FindUsersInRole(string roleName, string usernameToMatch) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string[] GetAllRoles() 
     { 
      throw new NotImplementedException(); 
     } 

     public override string[] GetRolesForUser(string username) 
     { 
      var user = _repository.GetUser(username); 

      return new string[] { user.Role.Name }; 
     } 

     public override string[] GetUsersInRole(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool IsUserInRole(string username, string roleName) 
     { 
      var user = _repository.GetUser(username); 

      return string.Compare(user.Role.Name, roleName, true) == 0; 
     } 

     public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool RoleExists(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

Esto funciona muy bien con restringir el acceso a controladores y acciones usando:

[Authorize(Roles = "Administrator")] 

sobre el controlador o la acción.

también quieren tener acceso restringido a algunas cosas en la vista, aunque usando:

HttpContext.Current.User.IsInRole("Administrator") 

Este método no es parte de mi RoleProvider, así que no está siendo anulado.

¿Alguien sabe cómo hacerlo para que este método también?

Respuesta

11

Si ha enganchado su RoleProvider como el proveedor de funciones para la aplicación en web.config, entonces esto debería funcionar de forma automática; el marco creará un RolePrincipal para un usuario autenticado en el inicio de la solicitud de que se llame al método GetRolesForUser de su proveedor de papel, pasando el nombre de la IIdentity como nombre de usuario.

La aplicación marco de IsInRole(string role) método RolePrincipal 's es algo como esto (He añadido los comentarios)

public bool IsInRole(string role) 
{ 
    if (_Identity == null) 
     throw new ProviderException(SR.GetString(SR.Role_Principal_not_fully_constructed)); 

    if (!_Identity.IsAuthenticated || role == null) 
     return false; 
    role = role.Trim(); 
    if (!IsRoleListCached) { 
     _Roles.Clear(); 

     // here the RoleProvider is used to get the roles for the user 
     // and are cached in a collection on the RolePrincipal so that 
     // they are only fetched once per request 
     string[] roles = Roles.Providers[_ProviderName].GetRolesForUser(Identity.Name); 
     foreach(string roleTemp in roles) 
      if (_Roles[roleTemp] == null) 
       _Roles.Add(roleTemp, String.Empty); 

     _IsRoleListCached = true; 
     _CachedListChanged = true; 
    } 
    return _Roles[role] != null; 
} 

Establecer un punto de interrupción en el interior de su método de RoleProvider GetRolesForUser para asegurarse de que está siendo llamado correctamente y también inspeccione el IPrincipal (HttpContext.Current.User) para asegurarse de que sea del tipo RolePrincipal para un usuario autenticado.

+0

Mi proveedor de funciones no contiene el método IsInRole sin embargo. Está heredando de RoleProvider y tiene el método IsUserInRole. – AnonyMouse

+3

El método IsInRole en HttpContext.Current.User está en un tipo que implementa IPrincipal. cuando tiene un RoleProvider registrado y una solicitud proviene de un usuario autenticado, el IPrincipal será una instancia de RolePrincipal. Puede ver en el método anterior que IsInRole en RolePrincipal llama al método GetRolesForUser de RoleProvider, de modo que es en el que necesita establecer un punto de interrupción para asegurarse de que se está llamando correctamente. –

5

lo siento tarde a la fiesta aquí;

Para el beneficio de otras personas con el mismo problema - Russ Cam's respuesta es el clavo a encontrar la respuesta.

En mi caso, mi costumbre roleManager no tenía 'enabled = "true" y cacheRolesInCookie = "true". Esto pareció detener el llamado a GetRolesForUser.

Código de Trabajo Para el web.config:

<roleManager defaultProvider="CustomUserRolesMVCRoleProvider" enabled="true" cacheRolesInCookie="true"> 

Realmente buen tutorial sobre este tema en http://www.brianlegg.com/post/2011/05/09/Implementing-your-own-RoleProvider-and-MembershipProvider-in-MVC-3.aspx

Cuestiones relacionadas