在授权属性角色有望在MVC 4不起作用 [英] Roles in Authorize Attribute does not work as expected in MVC 4

查看:132
本文介绍了在授权属性角色有望在MVC 4不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  

免责声明:我是新来的ASP.NET MVC 4,我习惯用的WebForms正在与&LT之前,这个项目;认证模式=无>


我在其中我对用户实体特定的角色,比如 ADMIN数据库 SUBADMIN 。我有独立的控制器在我的项目来处理的例如不同的角色, AdminController SubAdminController 我可以不同的视图根据他们的角色成功地将用户重定向到各自的看法。

我的问题是,当用户已登录,他们甚至可以他们都无缘access.This访问页意味着可能是我还没有建立正确的授权

我曾尝试?

我曾尝试与ADMIN角色过滤器的授权属性,因此只有管理员有权查看,如各自的看法:

  [授权(角色=ADMIN)]
    公共类AdminController:BaseController
    {
    ....
    }

这将用户重定向即使他成功验证这是在web.config中配置这样的登录页面:

 <身份验证模式=表格>
      <形式loginUrl =〜/首页/索引超时=2880/>
    < /认证>

请注意,如果我只是使用 [授权] ,而不是那么它的工作原理,但即使SubAdmin可以访问管理员的意见。

我曾尝试配置Web.config中的授权过这样的:

 <位置路径=管理>
    <&的System.Web GT;      <授权>
        <让角色=ADMIN/>        <拒绝用户=*/>
      < /授权>    < /system.web>
  < /地点>

这已经导致相同的结果,使用 [授权(角色=管理员)]

请注意,如果我安慰了以下

User.Identity.ToGenericUserIdentity()ROLENAME; 在我的 AdminController 然后我得到管理,我可以用它在我的操作方法来重新检查用户是否实际上是一个管理员或子管理员,但不是把它写下来作为我所有的操作方法检查的正确方法。

相关类:

  [Serializable接口]
    公共类GenericUser
    {        公共BOOL IsInRole(字符串角色){返回false; }        公共字符串角色名{获得;组; }
        公众诠释用户名{搞定;组; }
        公共字符串用户名{获得;组; }
    }    [Serializable接口]
    公共类GenericUserIdentity:IIdentity的
    {
        私人GenericUser genericUser;
        私人的FormsAuthenticationTicket票;        公共GenericUserIdentity(门票的FormsAuthenticationTicket)
        {
            VAR串行=新JsonSerializer();
            VAR读卡器=新JsonTextReader(新StringReader(ticket.UserData));
            genericUser = serializer.Deserialize< GenericUser>(读卡器);
            this.ticket =票;
        }        公共字符串AuthenticationType
        {
            {返回自定义; }
        }        公共BOOL IsAuthenticated
        {
            {返回票!= NULL; }
        }        公共字符串名称
        {
            {返回genericUser.UserName; }
        }        公共字符串ROLENAME
        {
            {返回genericUser.RoleName; }
        }        公众诠释用户名
        {
            {返回genericUser.UserID; }
        }    }公共静态类IdentityExtension
{
    公共静态GenericUserIdentity ToGenericUserIdentity(此的IIdentity身份)
    {
        VAR饼干= HttpContext.Current.Request.Cookies [FormsAuthentication.FormsCookieName]
        VAR ticketInfo = FormsAuthentication.Decrypt(cookie.Value);
        返回新GenericUserIdentity(ticketInfo);
    }
}

?如何验证?

在我的的HomeController 这表明在Index()动作登录页面,我已经建立了一个HttpPost Index操作是这样的:

 公众的ActionResult指数()
        {
            返回查看();
        }
 [HttpPost]
        公众的ActionResult指数(用户名字符串,字符串密码)
        {            UserInformation USERINFO = _userProvider.FindUserByName(用户名);            OrderProvider orderProvider =新OrderProvider(新OrderRepository());            如果(USERINFO = NULL&放大器;!&安培; string.Equals(userInfo.Password,密码,StringComparison.Ordinal))
            {
                如果(userInfo.isEnabled)
                {
                    GenericUser genericUser =新GenericUser(){用户名= userInfo.Email,用户名= userInfo.UserID,角色名= userInfo.RoleName};                    Response.SetAuthCookie< GenericUser>(genericUser.UserName,genericUser);                    如果(userInfo.RoleName ==ADMIN)
                    {
                        返回RedirectToAction(指数,管理);
                    }
                    否则,如果(userInfo.RoleName ==USER)
                    {
                        返回RedirectToAction(指数,客户);
                    }
                    否则,如果(userInfo.RoleName ==驱动程序)
                    {
                        返回RedirectToAction(指数,驱动程序);
                    }
                    否则,如果(userInfo.RoleName ==SUBADMIN)
                    {
                        返回RedirectToAction(指数,SubAdmin);
                    }
                }            }            ViewBag.Error = TRUE;            返回查看(「指数」);        }

请帮我解决this.Thanks。

修改

最后重写 AuthorizeCore 我的自定义属性的方法为我工作。

 公开枚举角色
    {
        ADMIN,SUBADMIN,USER,DRIVER
    }    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,继承= TRUE,的AllowMultiple = TRUE)]
    公共类AuthorizeUser:AuthorizeAttribute
    {
        公共AuthorizeUser(params对象[]角色)
        {
            如果(roles.Any(R =方式>!r.GetType()BASETYPE = typeof运算(枚举)))
                抛出新的ArgumentException(角色);            this.Roles =的string.join(,,roles.Select(R => Enum.GetName(r.GetType()中,r)));
        }保护覆盖布尔AuthorizeCore(HttpContextBase的HttpContext)
        {
            VAR饼干= HttpContext.Current.Request.Cookies [FormsAuthentication.FormsCookieName]
            VAR ticketInfo = FormsAuthentication.Decrypt(cookie.Value);            GenericUserIdentity鉴定者=新GenericUserIdentity(ticketInfo);
            如果(Roles.Contains(iden.RoleName))
                返回true;
            其他
                返回false;
        }
        }


解决方案

属性 [授权(角色=管理员)] 仅适用于内置的角色。结果
你有自己的 GenericUser.RoleName ,不会被用在这里。

您可以编写自己的 MyAuthorize 属性,但先问问自己很认真,为什么你在这里重新发明轮子。身份和成员的框架都可以和测试。当我看到一个 string.Equals(userInfo.Password,密码)我很怀疑你实现的安全性。

Disclaimer:I am new to ASP.NET MVC 4 and prior to this project,i was used to working with WebForms with <authentication mode="none">

I have a database in which i have specific roles against a user entity like ADMIN and SUBADMIN . I have separate controllers in my project to deal with different views for the different roles for example, AdminController and SubAdminController I can successfully redirect users to the respective views according to their roles.

My Issue is that when the users have logged in they can even access pages which they are not privileged to access.This implies that may be i have not set up authorization properly.

What i have tried?

I have tried the authorized attribute with ADMIN role filter so that only admins are authorized to view the respective views like:

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

This redirects the user even if he is successfully authenticated to the login page which is configured in web.config like this:

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

Note that if i just use [Authorize] instead then it works but even SubAdmin can gain access to the Admin views.

I have tried configuring the authorization in Web.config too like this:

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

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

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

    </system.web>
  </location>

This has lead to same results as using [Authorize(Roles="ADMIN")].

Note that if i console out the following

User.Identity.ToGenericUserIdentity().RoleName; in my AdminController then i get ADMIN and i can use it in my action methods to re check whether the user is actually an admin or sub admin but that is not the correct way to write it down as checks in all my action methods.

Related classes:

[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);
    }
}

And how do i authenticate?

In my HomeController which shows the login page on Index() action, i have set up a HttpPost Index action like this:

  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");

        }

Please help me solve this.Thanks.

EDIT

Finally overriding the AuthorizeCore method of my custom attribute worked for me.

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;
        }
        }

解决方案

The attribute [Authorize(Roles="ADMIN")] only works for the built-in Roles.
You have your own GenericUser.RoleName, that won't be used here.

You could write your own MyAuthorize attribute but first ask yourself very seriously why you are re-inventing the wheel here. The Identity and Membership frameworks are available and tested. When I see a string.Equals(userInfo.Password, password) I very much doubt the security of your implementation.

这篇关于在授权属性角色有望在MVC 4不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆