Model view controller 自定义角色提供程序与MVC的AuthorizeAttribute存在问题
我正在开发一个带有自定义角色提供程序的MVC 5应用程序,但似乎AuthorizeAttribute从未调用我的客户角色提供程序,我的代码如下: 我的客户提供商:Model view controller 自定义角色提供程序与MVC的AuthorizeAttribute存在问题,model-view-controller,provider,role,authorize-attribute,Model View Controller,Provider,Role,Authorize Attribute,我正在开发一个带有自定义角色提供程序的MVC 5应用程序,但似乎AuthorizeAttribute从未调用我的客户角色提供程序,我的代码如下: 我的客户提供商: namespace MyDomain { public class CustomRoleProvider : RoleProvider { public override string[] GetRolesForUser(string username) { u
namespace MyDomain
{
public class CustomRoleProvider : RoleProvider
{
public override string[] GetRolesForUser(string username)
{
using (MyContext objContext = new MyContext())
{
var objUser = objContext.Users.FirstOrDefault(x => x.Username == username);
if (objUser == null)
{
return null;
}
else
{
string[] ret = { objUser.Access_Levels.Name };
return ret;
}
}
}
public override bool IsUserInRole(string username, string roleName)
{
var userRoles = GetRolesForUser(username);
return userRoles.Contains(roleName);
}
}
我的控制器:
[Authorize(Roles = "Administrator")]
public class AdminController : Controller
和Web.Config:
<system.web>
<roleManager defaultProvider="CustomRoleProvider" enabled="true" >
<providers>
<clear />
<add name="CustomRoleProvider" type="Online_Storage_Portal.CustomRoleProvider" cacheTimeoutInMinutes="30"/>
</providers>
</roleManager>
</system.web>
此外,我的自定义角色提供程序与其他控制器位于同一项目中,我可以在控制器中使用以下代码调用我的自定义角色提供程序方法
字符串[]角色=角色。GetRolesForUser(用户名)
但是具有[Authorize(Roles=“Administrator”)]的控制器始终将页面重定向到登录屏幕,即使用户登录和角色都有值
请帮忙 我相信我已经找到了你问题的根源。我假设您正在使用Windows身份验证,并尝试使用自定义角色提供程序来代替自动加载的Windows组。查看MVC AuthorizeAttribute源,您会发现它实际上正在调用Principal.IsInRole。根据MSDN: InRole首先检查IsRoleListCached属性,以确定当前用户的角色名称缓存列表是否可用。如果IsRoleListCached属性为true,则检查指定角色的缓存列表。如果IsInRole方法在缓存列表中找到指定的角色,则返回true。 如果IsInRole找不到指定的角色,它将调用默认提供程序实例的GetRolesForUser方法,以确定用户名是否与配置的ApplicationName值的数据源中的角色相关联 所以我猜,因为主体是一个Windows主体,所以它将填充和缓存它的角色。当调用IsInRole时,它会说‘嘿,我已经有了角色,为什么我要回到提供者那里再次获取角色?’ 你可以做的是这样的事情:
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
WindowsIdentity identity = HttpContext.Current.Request.LogonUserIdentity;
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new GenericIdentity(identity.Name), Roles.GetRolesForUser());
}
这将从HttpContext中提取windows标识,使用该名称显式地从自定义提供程序获取角色,然后在请求上添加新的GenericPrincipal。我进一步实现了一些逻辑,将角色存储在加密的cookie中,这样我们就不必在每个请求上都使用角色提供程序
void Application_PostAuthenticateRequest()
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket authTicket;
if (authCookie == null || authCookie.Value == "")
{
string[] getRoles = Roles.GetRolesForUser();
authTicket = new FormsAuthenticationTicket(1,
User.Identity.Name,
DateTime.Now,
DateTime.Now.AddMinutes(20),
true,
String.Join(";", getRoles));
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Current.Response.Cookies.Add(authCookie);
}
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
string[] roles = authTicket.UserData.Split(';');
if (Context.User != null)
Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
}
谢谢你的评论Dan。我可以做同样的事情,除了使用CustomerPrincipal覆盖WindowsPrincipal IsInRole方法以提供附加功能。这里也一样。Dan,你就是那个人。不知道身份验证后,包装WindowsPrincipal的概念,或者默认impl只是使用缓存d角色。