处理多重角色在MVC - 基于行动无障碍 [英] Handling Multiple Roles in MVC - Action-based Accessibility

查看:152
本文介绍了处理多重角色在MVC - 基于行动无障碍的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在有一个项目,我似乎已经跑进关于角色的问题,我想我会得到有关如何最好地处理这个问题的一些意见。

I currently have a project that I seem to have ran into an issue regarding Roles and thought I would get some opinions on how to best handle the problem.

,系统将要求不仅控制特定区域的访问权限,而且还使用系统功能可编辑的,灵活的角色(添加用户,修改用户信息,查看报表等)

The system will require editable, flexible roles that control not only the access of specific areas, but also the use of system functions (Adding Users, Editing Users, Viewing Reports etc.)

目前,该系统允许用户有多个角色,每个角色的那些已经明确定义的访问/行动领域,例如:

The system currently allows users to have multiple roles, each of those roles has explicitly defined areas of access/actions, for example:


  • 角色A 可以访问区1,2,3和可以添加用户。

  • Role B的可以访问区1,5,7,并且可以修改用户。

  • 角色ç可以访问区4,6,只查看用户。

  • Role A can access areas 1,2,3 and can Add Users.
  • Role B can access areas 1,5,7 and can Modify Users.
  • Role C can access areas 4,6 and only View Users.

因此​​用户可以在角色A和C,并因此获得:1,2,3,4和6,并且可以添加和查看用户

so a User could be in Roles A and C, and thus access : 1,2,3,4 and 6, and could Add and View Users.

我的第一个解决方案是创建一个将所有的访问/接入方案的可能领域的存储到一个字典,像这样一本字典:

My first solution was to create a dictionary that would store all of the possible areas of access/access options into a Dictionary like so:

Dictionary<string,bool>

然后,当它被实例它拉所有从数据库中的属性和然后通过角色迭代以确定它们是否是可访问的

then when it is instantiated it pulls all of the properties from the database and then iterates through the roles to determine if they are accessible.

所有的当前工作得很好 - 但该项目是相当的Javascript / jQuery的密集这么多的这些选项是由客户端函数调用。我试图避免包所有这些客户端的功能搭配:

All of that currently works just fine - however the project is quite Javascript/jQuery intensive so many of these options are called by client-side functions. I am trying to avoid having to wrap all of these client side functions with:

<%if(AccessDictionary[key])
     //Enable or Disable Action
<%}%>

所以基本上,我想知道以下几点:


  1. 在用户登录,什么是存储该词典的最佳方式?静态?在会话吗

  2. 什么会是这样的字典将在视图轻松访问存储的最好方法? (由于我目前看到周围环绕我的客户端功能没办法)

  1. After a user logs in, what is the best way to store this Dictionary? Statically? In the Session?
  2. What would be the best method of storage such that the Dictionary will be easily accessed in the View? (As I currently see no way around wrapping my client-side functions)

任何意见或想法将不胜AP preciated!

Any advice or ideas would be greatly appreciated!

推荐答案

我会存储在身份验证cookie的用户数据的一部分,此信息。因此,当用户登录:

I would store this information in the user data part of the authentication cookie. So when a user logs in:

public ActionResult Login(string username, string password)
{
    // TODO: validate username/password couple and 
    // if they are valid get the roles for the user

    var roles = "RoleA|RoleC";
    var ticket = new FormsAuthenticationTicket(
        1, 
        username,
        DateTime.Now, 
        DateTime.Now.AddMilliseconds(FormsAuthentication.Timeout.TotalMilliseconds), 
        false, 
        roles
    );
    var encryptedTicket = FormsAuthentication.Encrypt(ticket);
    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
    {
        // IIRC this property is only available in .NET 4.0,
        // so you might need a constant here to match the domain property
        // in the <forms> tag of the web.config
        Domain = FormsAuthentication.CookieDomain,
        HttpOnly = true,
        Secure = FormsAuthentication.RequireSSL,
    };
    Response.AppendCookie(authCookie);
    return RedirectToAction("SomeSecureAction");
}

然后我会写一个会照顾读取和解析的身份验证票证和HttpContext.User属性的通用用户存储与其对应的角色自定义属性authroize:

Then I would write a custom authroize attribute which will take care of reading and parsing the authentication ticket and store a generic user in the HttpContext.User property with its corresponding roles:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext.User.Identity.IsAuthenticated)
        {
            var authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie != null)
            {
                var ticket = FormsAuthentication.Decrypt(authCookie.Value);
                var roles = ticket.UserData.Split('|');
                var identity = new GenericIdentity(ticket.Name);
                httpContext.User = new GenericPrincipal(identity, roles);
            }
        }
        return base.AuthorizeCore(httpContext);
    }
}

接下来,您可以装饰你的控制器/与这个属性的动作处理授权:

Next you could decorate your controllers/actions with this attribute to handle authorization:

// Only users that have RoleA or RoleB can access this action
// Note that this works only with OR => that's how the base
// authorize attribute is implemented. If you need to handle AND
// you will need to completely short-circuit the base method call
// in your custom authroize attribute and simply handle this
// case manually
[MyAuthorize(Roles = "RoleA,RoleB")]
public ActionResult Foo()
{
    ...
}

为了检查用户是否只是一个给定角色:

In order to check whether a user is in a given role simply:

bool isInRole = User.IsInRole("RoleC");

有了这些信息,你现在可以开始如何组织你的视​​图模型思想武装。在这些视图模型我将包括布尔属性,如 CanEdit CanViewReport ,...这将是由填充控制器。

Armed with this information you can now start thinking of how to organize your view models. In those view models I would include boolean properties such as CanEdit, CanViewReport, ... which will be populated by the controller.

现在,如果你需要这个映射中的每个动作和看法,事情可能会重复和枯燥。这是全球性的自定义操作过滤器发挥作用(他们没有真正在ASP.NET MVC 2,仅在ASP.NET MVC 3存在,因此,您可能需要装饰着这个动作过滤器模拟或多或少同一个基本控制器功能)。您只需定义这样的全球行动,过滤器,每次操作后执行,并注入一些常见的视图模型到的ViewData(圣....,无法相信我发音的那些话),从而使其可在一个横向的所有视图其他操作方式。

Now if you need this mapping in each action and views things might get repetitive and boring. This is where global custom action filters come into play (they don't really exist in ASP.NET MVC 2, only in ASP.NET MVC 3 so you might need a base controller decorated with this action filter which simulates more or less the same functionality). You simply define such global action filter which executes after each action and injects some common view model to the ViewData (holy ...., can't believe I am pronouncing those words) and thus make it available to all views in a transverse of the other actions manner.

终于在视图中,您会以包括或不是网站的不同区域检查这些布尔值属性。至于如果这些区域不在DOM present再code将不运行的JavaScript code而言,如果它被不显眼地AJAXifying站点然后领域。如果你需要更为精细的控制,你总是可以使用HTML5 数据 - * 属性上的DOM元素给提示到您的外部JavaScript函数对用户的权限

And finally in the view you would check those boolean value properties in order to include or not different areas of the site. As far as the javascript code is concerned if it is unobtrusively AJAXifying areas of the site then if those areas are not present in the DOM then this code won't run. And if you needed more fine grained control you could always use HTML5 data-* attributes on your DOM elements to give hints to your external javascript functions on the authorizations of the user.

这篇关于处理多重角色在MVC - 基于行动无障碍的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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