Model view controller 自定义角色提供程序与MVC的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

我正在开发一个带有自定义角色提供程序的MVC 5应用程序,但似乎AuthorizeAttribute从未调用我的客户角色提供程序,我的代码如下:

我的客户提供商:

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角色。