我有一个MVC应用程序,我为它编写了一个自定义角色提供程序,如下所示:
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();
}
}
}
这非常适用于使用以下方法限制对控制器和操作的访问:
[Authorize(Roles = "Administrator")]
在控制器或行动之上。
我还希望使用以下方式限制访问视图中的某些内容:
HttpContext.Current.User.IsInRole("Administrator")
此方法不属于我的角色提供者,但不会被覆盖。
有没有人知道如何为这种方法做到这一点?
答案 0 :(得分:11)
如果您已将RoleProvider作为web.config中应用程序的角色提供程序挂钩,那么这应该会自动生效;框架将在请求开始时为经过身份验证的用户创建RolePrincipal
,该用户将在您的角色提供程序上调用GetRolesForUser
方法,并将IIdentity
中的名称作为用户名传递。
RolePrincipal
的{{1}}方法的框架实现是这样的(我添加了评论)
IsInRole(string role)
在RoleProvider 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;
}
方法中设置一个断点,以确保正确调用它,并检查GetRolesForUser
(IPrincipal
)以确保它的类型为{{1对于经过身份验证的用户。
答案 1 :(得分:5)
抱歉,我在这里参加派对迟到了;
为了其他有相同问题的人的利益 - Russ Cam's答案可以找到答案。
就我而言,我的自定义roleManager没有'enabled =“true”和cacheRolesInCookie =“true”。这似乎阻止了GetRolesForUser被调用。
工作代码对于web.config:
<roleManager defaultProvider="CustomUserRolesMVCRoleProvider" enabled="true" cacheRolesInCookie="true">
上有关此主题的非常好的教程