与MVC的网站有一定的要求细化的权限 [英] Granular permissions with certain requirements for an MVC site

查看:224
本文介绍了与MVC的网站有一定的要求细化的权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不喜欢内置的会员供应商。我决定推出自己的。我想拿出的行动水平执行授权的好方法。下面是我的试图要求的由去:

I don't like the built in membership providers. I've decided to roll my own. I'm trying to come up with a good method for performing authorization at the action level. Here are the requirements that I'm trying to go by:


  1. 属性的用法 - 我喜欢这个,因为它在调用堆栈一个相当高的水平控制,是一个不错的地方,组织权限

  2. 无幻字符串 - 这就是为什么我偏离从目前的角色提供远的原因。我不想离开琴弦躺在身边,不能轻易改名。

  3. 权限应可组成的有一个的其他权限。例如:读写许可。就像有一个枚举OR符号。

  1. Attribute usage - I like this since it controls at a very high level in the call stack and is a nice place to organize permissions.
  2. No magic strings - This is a reason why I'm straying away from the current role providers. I don't want to leave strings lying around that can't be easily renamed.
  3. Permissions should can be composed of one other permission. Example: ReadWrite has permission for Read. Just like or'ing with an enum.

请注意:有些人认为这组要求过于宽泛(见注释)。我不这么认为,我认为他们是非常简单的。

NOTE: Some think this set of requirements is too broad (see comments). I don't think so, I think they're fairly straightforward.

最大的搅局者是属性的使用。只能有恒恩pressions的typeof前pressions或属性参数类型的数组创建前pression。

The biggest showstopper is attribute usage. There can only be "constant expressions, typeof expressions or array creation expression of an attribute parameter type".

我在想也许有这样的事情,使操作具有静态访问。里面的属性,这将转换的INT实际权限或东西...:

I was thinking of perhaps having something like this to make operations have static access. Inside of the attribute, it would "convert" the int to the actual Permission or something...:

public static class Operations
{
    public static class SectionA
    {
        public const int Read = 1;
        public const int ReadWrite = 2;
    }

    public static class SectionB
    {
        // ... and so on...
    }
}

但它确实限制组成。我敢肯定,你在想你为什么不走枚举路线?好,我想计划要改变环境,不希望限制到32(INT)或64(长)操作,并有后来做了大规模的改写(也在这只是丑陋的DB)。

But it really limits composition. I'm sure you're thinking "why don't you go the enum route?" well I want to plan for things to change and don't want to limit to 32 (int) or 64 (long) operations and have to do a massive rewrite later (also in the db that's just ugly).

此外,如果有比动作/控制器属性更好的选择,那么我所有的耳朵建议。

Also, if there is a better alternative than attributes on actions/controllers, then I'm all ears for suggestions.

编辑:另外从<一个href=\"http://stackoverflow.com/questions/1060760/what-to-do-when-bit-mask-flags-enum-gets-too-large\">this帖子,我读过有关 BitArray 类。看来的样的的丑陋,尤其是在数据库中存储的任意

Also from this post, I've read about the BitArray class. It seems kind of ugly, especially with the arbitrary storage in the database.

推荐答案

首先,我要感谢你拉我进回答这个问题;)

First of all, I have to thank you for sucking me into answering this ;)

这是一个长期的答案,只是一个起点。你必须弄清楚如何将角色分配给用户,以及如何重新创建它们在的AuthenticateRequest

This is a long answer, and is only a starting point. You have to figure out how to assign roles to users and how to recreate them in the AuthenticateRequest.

如果这不回答你的问题,我希望这将是一种鼓舞。尽情享受吧!

If this does not answer your question, I hope it will be an inspiration. Enjoy!

装饰控制器动作

我开始装点在默认的两个动作的HomeController

I started to decorate the two actions in the default HomeController:

    [AuthorizeRoles(Role.Read)]
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    [AuthorizeRoles(Role.Write)]
    public ActionResult About()
    {
        return View();
    }

在读写角色的所有用户应该再被授予访问权限。我选择在这里使用一个枚举作为魔术字符串类型安全的占位符。此枚举的作用无非是一个占位符别人。没有复合枚举值,即必须保持在其他地方。后来更多。

All users in the ReadWrite role should then be granted access. I opted here to use an enum as a type safe placeholder for the magic strings. The role of this enum is nothing else than being a placeholder. There are no composite enum values, that has to be maintained somewhere else. More on that later.

public enum Role
{
    Read,
    Write,
    ReadWrite
}

实现新的授权属性

由于琴弦都走了,我需要一个新的授权属性:

Since the strings are gone, I need a new authorize attribute:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    private readonly RoleSet authorizedRoles;

    public AuthorizeRolesAttribute(params Role[] roles)
    {
        authorizedRoles = new RoleSet(roles);
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return authorizedRoles.Includes(httpContext.User);
    }
}

RoleSet 包装一组枚举值,并验证如果的IPrincipal 就是其中之一的成员:

The RoleSet wraps a set of enum values and verifies if an IPrincipal is a member of one of them:

public class RoleSet
{
    public RoleSet(IEnumerable<Role> roles)
    {
        Names = roles.Select(role => role.ToString());
    }

    public bool Includes(IPrincipal user)
    {
        return Names.Any(user.IsInRole);
    }

    public bool Includes(string role)
    {
        return Names.Contains(role);
    }

    public IEnumerable<string> Names { get; private set; }
}

维护角色

CompositeRoleSet 是复合角色注册并处理。 CreateDefault()是所有复合材料登记。
解析()将角色(枚举值)的列表和复合材料转换成他们唯一的同行。

The CompositeRoleSet is where composite roles are registered and handled. CreateDefault() is where all composites are registered. Resolve() will take a list of roles (enum values) and convert the composites to their single counterparts.

public class CompositeRoleSet
{
    public static CompositeRoleSet CreateDefault()
    {
        var set = new CompositeRoleSet();
        set.Register(Role.ReadWrite, Role.Read, Role.Write);
        return set;
    }

    private readonly Dictionary<Role, Role[]> compositeRoles = new Dictionary<Role, Role[]>();

    private void Register(Role composite, params Role[] contains)
    {
        compositeRoles.Add(composite, contains);
    }

    public RoleSet Resolve(params Role[] roles)
    {
        return new RoleSet(roles.SelectMany(Resolve));
    }

    private IEnumerable<Role> Resolve(Role role)
    {
        Role[] roles;
        if (compositeRoles.TryGetValue(role, out roles) == false)
        {
            roles = new[] {role};
        }

        return roles;
    }
}

接线起来

我们需要一个身份验证的用户去努力。我欺骗和硬codeD之一的Global.asax:

We need an authenticated user to work on. I cheated and hard-coded one in global.asax:

    public MvcApplication()
    {
        AuthenticateRequest += OnAuthenticateRequest;
    }

    private void OnAuthenticateRequest(object sender, EventArgs eventArgs)
    {
        var allRoles = CompositeRoleSet.CreateDefault();
        var roles = allRoles.Resolve(Role.ReadWrite);
        Context.User = new ApplicationUser(roles);
    }

最后,我们需要一个的IPrincipal 这明白这一切:

public class ApplicationUser : IPrincipal
{
    private readonly RoleSet roles;

    public ApplicationUser(RoleSet roles)
    {
        this.roles = roles;
    }

    public bool IsInRole(string role)
    {
        return roles.Includes(role);
    }

    public IIdentity Identity
    {
        get { return new GenericIdentity("User"); }
    }
}

这篇关于与MVC的网站有一定的要求细化的权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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