授权属性中的角色在MVC 4中无法正常工作

时间:2015-03-22 08:14:49

标签: c# asp.net asp.net-mvc asp.net-mvc-4

(我是ASP.NET MVC 4的新手,在此项目之前,我习惯使用<authentication mode="none">处理WebForms。

我有一个数据库,我对ADMINSUBADMIN这样的用户实体有特定的角色。我的项目中有单独的控制器来处理不同角色的不同视图,例如AdminControllerSubAdminController我可以根据用户的角色成功地将用户重定向到相应的视图。

我的问题是,当用户登录后,他们甚至可以访问他们无权访问的页面。这意味着我可能没有正确设置授权。

我尝试了什么?

我已尝试使用ADMIN角色过滤器的授权属性,以便只有管理员才有权查看相应的视图,如:

[Authorize(Roles="ADMIN")]
    public class AdminController : BaseController
    {
    ....
    }

即使用户已成功通过对web.config中配置的登录页面进行身份验证,也会重定向用户,如下所示:

 <authentication mode="Forms">
      <forms loginUrl="~/Home/Index" timeout="2880" />
    </authentication>

请注意,如果我只使用[Authorize]代替它,那么即使是SubAdmin也可以访问管理员视图。

我已尝试在Web.config中配置授权,如下所示:

<location path="Admin">
    <system.web>

      <authorization>
        <allow roles="ADMIN"/> 

        <deny users="*"/> 
      </authorization>

    </system.web>
  </location>

这导致与使用[Authorize(Roles="ADMIN")]相同的结果。

请注意,如果我控制了以下

User.Identity.ToGenericUserIdentity().RoleName;

AdminController然后我得到ADMIN我可以在我的操作方法中使用它来重新检查用户是否实际上是管理员或子管理员但不是把它写成所有行动方法的正确方法。

相关课程:

[Serializable]
    public class GenericUser
    {

        public bool IsInRole(string role) { return false; }



        public string RoleName { get; set; }
        public int UserID { get; set; }
        public string UserName { get; set; }
    }

    [Serializable]
    public class GenericUserIdentity : IIdentity
    {
        private GenericUser genericUser;
        private FormsAuthenticationTicket ticket;

        public GenericUserIdentity(FormsAuthenticationTicket ticket)
        {
            var serializer = new JsonSerializer();
            var reader = new JsonTextReader(new StringReader(ticket.UserData));
            genericUser = serializer.Deserialize<GenericUser>(reader);
            this.ticket = ticket;
        }

        public string AuthenticationType
        {
            get { return "Custom"; }
        }

        public bool IsAuthenticated
        {
            get { return ticket != null; }
        }

        public string Name
        {
            get { return genericUser.UserName; }
        }

        public string RoleName
        {
            get { return genericUser.RoleName; }
        }

        public int UserID
        {
            get { return genericUser.UserID; }
        }



    }

public static class IdentityExtension
{
    public static GenericUserIdentity ToGenericUserIdentity(this IIdentity identity)
    {
        var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        var ticketInfo = FormsAuthentication.Decrypt(cookie.Value);
        return new GenericUserIdentity(ticketInfo);
    }
}

我如何进行身份验证?

在显示Index()操作登录页面的HomeController中,我设置了一个HttpPost Index操作,如下所示:

  public ActionResult Index()
        {
            return View();
        }
 [HttpPost]
        public ActionResult Index(string username,string password)
        {

            UserInformation userInfo = _userProvider.FindUserByName(username);

            OrderProvider orderProvider = new OrderProvider(new OrderRepository());

            if (userInfo != null && string.Equals(userInfo.Password, password,StringComparison.Ordinal))
            {
                if (userInfo.isEnabled)
                {
                    GenericUser genericUser = new GenericUser() { UserName = userInfo.Email, UserID = userInfo.UserID, RoleName = userInfo.RoleName };

                    Response.SetAuthCookie<GenericUser>(genericUser.UserName, genericUser);

                    if (userInfo.RoleName == "ADMIN")
                    {
                        return RedirectToAction("Index", "Admin");
                    }
                    else if (userInfo.RoleName == "USER")
                    {
                        return RedirectToAction("Index", "Customer");
                    }
                    else if (userInfo.RoleName == "DRIVER")
                    {
                        return RedirectToAction("Index", "Driver");
                    }
                    else if (userInfo.RoleName == "SUBADMIN")
                    {
                        return RedirectToAction("Index", "SubAdmin");
                    }
                }



            }

            ViewBag.Error = true;

            return View("Index");

        }

修改

最后覆盖我的自定义属性的AuthorizeCore方法对我有效。

public enum Role
    {
        ADMIN, SUBADMIN, USER, DRIVER
    }

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
    public class AuthorizeUser : AuthorizeAttribute
    {
        public AuthorizeUser(params object[] roles)
        {
            if (roles.Any(r => r.GetType().BaseType != typeof(Enum)))
                throw new ArgumentException("roles");

            this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));
        }



protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
            var ticketInfo = FormsAuthentication.Decrypt(cookie.Value);

            GenericUserIdentity iden = new GenericUserIdentity(ticketInfo);
            if (Roles.Contains(iden.RoleName))
                return true;
            else
                return false;
        }
        }

1 个答案:

答案 0 :(得分:3)

属性[Authorize(Roles="ADMIN")]仅适用于内置角色 你有自己的GenericUser.RoleName,这里不会使用它。

您可以编写自己的MyAuthorize属性,但首先要非常认真地问自己为什么要在这里重新发明轮子。身份和成员资格框架可供使用和测试。当我看到string.Equals(userInfo.Password, password)时,我非常怀疑您的实施的安全性。