使用枚举标志位的基于WPF权限的授权



我已经做C#一个月了,所以请原谅这个问题的"地方性",但我研究了几个小时,遇到了困难

我看到了使用IIdentityIPrincipal的WPF应用程序的基于角色的授权的左右示例。

然而,我找不到太多关于基于权限的授权方法的信息,在这个应用程序中,想象一下没有组,只有权限和用户列表,你可以为任何人分配任何权限。

我希望能够:

1) 能够基于用户权限控制UI/元素,状态为:Enabled、ReadOnly、Invisible、Collapsed(如下所示https://uiauth.codeplex.com/)
2) 能够在类或方法级别指定需要哪些权限(类似于http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/)

代替:

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]

我想要一些类似的东西:

[PrincipalPermission(SecurityAction.Demand, Permission = "Can add users")]

现在,我看到如何做到这一点的唯一方法是利用ICommand,并在CanExecute方法中放入授权逻辑,使用大量的字符串比较来查看用户是否具有执行请求操作所需的权限,如:

// Employee class
public bool HasRight(SecurityRight right)
{
    return employee.Permissions.Contains(right);
}
// Implementation, check if employee has right to continue
if (employee.HasRight(db.SecurityRights.Single(sr => sr.Description == "Can edit users")))
{
    // Allowed to perform action
}
else
{
    // User does not have right to continue
    throw SecurityException;
}

有人告诉我,Enum Flags可能就是我想要的。在C#中,[Flags]枚举属性是什么意思?

我认为我理解enum/flag/bits,但不足以完成实现。。。

如果我有:

员工模型
EmployeeViewModel
ThingTwoModel
精简TwoViewModel
MainView

我不知道一切都去了哪里,也不知道如何把它们联系在一起。。。。以下是我目前所拥有的(我意识到这不是一个有效的例子……这是我的问题!):

    [Flags]
    public enum Permissions
    {
        None = 0,
        Create = 1 << 0,
        Read = 1 << 1,
        Update = 1 << 2,
        Delete = 1 << 3,
        User = 1 << 4,
        Group = 1 << 5
    }
    public static void testFlag()
    {
        Permissions p;
        var x = p.HasFlag(Permissions.Update) && p.HasFlag(Permissions.User);
        var desiredPermissions = Permissions.User | Permissions.Read | Permissions.Create;
        if (x & p == desiredPermissions)
        {
            //the user can be created and read by this operator
        }
    }

感谢您的指导。

好吧,testFlag不会像现在这样工作。我想你想要一些类似(LINQPad c#程序片段)的东西:

void Main()
{
    //can create user but not read the information back
    var userCanBeCreatedPermission = Permissions.Create | Permissions.User;
    //can create and readback
    var userCanBeCreatedAndReadBackPermission = userCanBeCreatedPermission | Permissions.Read;
    userCanBeCreatedPermission.HasFlag(Permissions.User).Dump(); //returns true
    (userCanBeCreatedPermission.HasFlag(Permissions.User) && userCanBeCreatedPermission.HasFlag(Permissions.Read)).Dump(); //returns false
    //alternative way of checking flags is to combine the flags and do an And mask check
    //the above can be written as
    ((userCanBeCreatedPermission & (Permissions.User | Permissions.Read)) == (Permissions.User | Permissions.Read)).Dump(); //returns false
    //using a variable to have combined permissions for readibility & using And mask:
    var desiredPermissions = Permissions.User | Permissions.Read;
    //checking with user that has both Create & Read permissions
    ((userCanBeCreatedAndReadBackPermission & desiredPermissions) == desiredPermissions).Dump(); // returns true because the user information can be read back by this user
    ((userCanBeCreatedAndReadBackPermission & Permissions.Delete) == Permissions.Delete).Dump(); // returns false because the user can't be deleted
}
[Flags]
public enum Permissions
{
   None = 0,
   Create = 1 << 0,
   Read = 1 << 1,
   Update = 1 << 2,
   Delete = 1 << 3,
   User = 1 << 4,
   Group = 1 << 5
}

这能回答你的问题吗?

最终解决方案(.linq):

void Main()
{
    // Permissions definition
    var userCreate = new Authorization<User>(Permissions.Create);
    var userRead = new Authorization<User>(Permissions.Read);
    var carrotCreate = new Authorization<Carrot>(Permissions.Create);
    var carrotRead = new Authorization<Carrot>(Permissions.Read);
    // User
    var user = new User();
    // User has no permissions yet
    if(user.IsAuthorized<User>(Permissions.Create))
        "I can create User".Dump();
    else
        "No creating User for me".Dump();
    // Now user can Create users
    user.Authorizations.Add(userCreate);            
    if(user.IsAuthorized<User>(Permissions.Create))
        "I can create User".Dump();
    else
        "No creating User for me".Dump();
    // User can read carrots
    user.Authorizations.Add(carrotRead);
    if(user.IsAuthorized<Carrot>(Permissions.Create))
        "I can create carrots".Dump();
    else
        "No creating carrots for me".Dump();
    if(user.IsAuthorized<Carrot>(Permissions.Read))
        "I can read carrots".Dump();
    else
        "No reading carrots for me".Dump();
    // User can now create carrots
    user.Authorizations.Add(carrotCreate);
    if(user.IsAuthorized<Carrot>(Permissions.Create))
        "I can create carrots".Dump();
    else
        "No creating carrots for me".Dump();            
}
[Flags]
public enum Permissions : ulong
{
    Create = 1 << 0,
    Read = 1 << 1,
    Update = 1 << 2,
    Delete = 1 << 3
}
public abstract class Auth{
}
public class Authorization<T> : Auth {
    public Authorization(Permissions permissions){ this.Permissions = permissions; }
    public Permissions Permissions {get;set;}
}
public class Carrot{
    public int Id{get; set;}
}
public class User{
    public User(){ Authorizations = new List<Auth>(); }
    public List<Auth> Authorizations{get; set;}
    public bool IsAuthorized<T>(Permissions permission){
        foreach(var auth in Authorizations)
            if(auth is Authorization<T>){
                var a = auth as Authorization<T>;
                if(a.Permissions == permission)
                    return true;
            }
        return false;
    }
}

最新更新