I have an MVC app and I wrote a custom roleprovider for it as shown:
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();
}
}
}
This works really well with restricting access to controllers and actions using:
[Authorize(Roles = "Administrator")]
above the controller or action.
I also want restricted access to some things in the view though using:
HttpContext.Current.User.IsInRole("Administrator")
This method isn't part of my roleprovider though so isn't getting overridden.
Does anyone know how to do it for this method as well?
If you've hooked your RoleProvider as the role provider for the application in web.config, then this should work automatically; the framework will create a RolePrincipal
for an authenticated user at the start of the request that will call the GetRolesForUser
method on your role provider, passing the name from the IIdentity
as the user name.
The framework implementation of RolePrincipal
's IsInRole(string role)
method is something like this (I've added comments)
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;
}
Set a breakpoint inside of your RoleProvider GetRolesForUser
method to ensure that it is being called correctly and also inspect the IPrincipal
(HttpContext.Current.User
) to ensure that it is of type RolePrincipal
for an authenticated user.
Sorry I am late to the party here;
For the benefit of other people with the same problem - Russ Cam's answer is spot on to finding the answer.
In my case, my custom roleManager did not have 'enabled="true" and cacheRolesInCookie="true". This seemed to stop the GetRolesForUser being called.
Working Code For the web.config:
<roleManager defaultProvider="CustomUserRolesMVCRoleProvider" enabled="true" cacheRolesInCookie="true">
Really Good Tutorial on this topic at http://www.brianlegg.com/post/2011/05/09/Implementing-your-own-RoleProvider-and-MembershipProvider-in-MVC-3.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With