2011-11-01 4 views
8

Ho un app MVC e ho scritto un RoleProvider personalizzato per come mostrato:MVC personalizzato RoleProvider come collegarlo al 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(); 
     } 
    } 
} 

questo funziona davvero bene con limitando l'accesso a controllori e azioni utilizzando:

[Authorize(Roles = "Administrator")] 

sopra il controller o l'azione.

Voglio anche l'accesso limitato ad alcune cose in vista però con:

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

Questo metodo non fa parte del mio RoleProvider anche se così non è sempre ignorata.

Qualcuno sa come farlo anche per questo metodo?

risposta

11

Se hai collegato il tuo RoleProvider come provider di ruolo per l'applicazione in web.config, allora questo dovrebbe funzionare automaticamente; il framework creerà un RolePrincipal per un utente autenticato all'inizio della richiesta che chiamerà il metodo GetRolesForUser sul proprio fornitore di ruolo, passando il nome dallo IIdentity come nome utente.

L'implementazione quadro del metodo di RolePrincipal s' IsInRole(string role) è qualcosa di simile (ho i commenti aggiunti)

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; 
} 

Impostare un punto di interruzione all'interno del vostro metodo di RoleProvider GetRolesForUser per garantire che essa è chiamata in modo corretto e anche ispezionare IPrincipal (HttpContext.Current.User) per assicurarsi che sia di tipo RolePrincipal per un utente autenticato.

+0

mio provider di ruoli non contiene il metodo IsInRole però. È ereditato da RoleProvider e ha il metodo IsUserInRole. – AnonyMouse

+3

Il metodo IsInRole su HttpContext.Current.User è su un tipo che implementa IPrincipal. quando hai un RoleProvider registrato e una richiesta arriva da un utente autenticato, l'IPrincipal sarà un'istanza di RolePrincipal. È possibile vedere dal metodo precedente che IsInRole su RolePrincipal chiama il metodo GetRolesForUser di RoleProvider in modo che sia quello in cui è necessario impostare un punto di interruzione per assicurarsi che venga chiamato correttamente. –

5

Scusate, sono in ritardo per la festa qui;

Per il beneficio di altre persone con lo stesso problema - Russ Cam's la risposta è perfetta per trovare la risposta.

Nel mio caso, il mio roleManager personalizzato non ha 'enabled = "true" e cacheRolesInCookie = "true". Sembrava che ciò impedisse il richiamo di GetRolesForUser.

codice di lavoro per il web.config:

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

Davvero buon tutorial su questo argomento in http://www.brianlegg.com/post/2011/05/09/Implementing-your-own-RoleProvider-and-MembershipProvider-in-MVC-3.aspx

Problemi correlati