权限比角色复杂得多。
通常可以有诸如 CreateEditDelete 之类的权限组……但它们也可以是细粒度的子集,例如“创建”、“编辑”、“删除”
我解决这个问题的方法是创建一个 PermissionsManger 类,该类可以确定用户应该拥有哪些权限给业务规则上下文和他们的 AD 角色。
我使用按位标志来帮助简化细粒度权限的复杂性。
如何将角色映射到权限完全取决于您。
using System;
using System.Linq;
using System.Security.Principal;
// Install-Package FluentAssertions -Pre
using FluentAssertions;
public static class ExtensionsForIPrincipal
{
public static bool HasPermission(this IPrincipal principal, Permissions permission)
{
return PermissionsManager.GetUserPermissions(principal).HasFlag(permission);
}
public static bool IsInRole(this IPrincipal principal, params string[] roleNames)
{
return roleNames.Any(principal.IsInRole);
}
}
public static class PermissionsManager
{
public static Permissions GetUserPermissions(IPrincipal user)
{
if ( user.IsInRole("admin") )
{
return Permissions.All;
}
var userPermissions = Permissions.None;
if ( user.IsInRole("staff", "user") )
{
userPermissions |= Permissions.QueryUsers;
}
if ( user.IsInRole("staff") )
{
userPermissions |= Permissions.PermissionsCreateEditDeleteSomething | Permissions.QueryUsers;
}
if ( user.IsInRole("editor") )
{
userPermissions |= Permissions.PublishSomething;
}
return userPermissions;
}
}
[Flags]
public enum Permissions
{
None = 0,
CreateSomething = 1,
EditSomething = 2,
DeleteSomething = 4,
PublishSomething = 8,
QueryUsers = 16,
PermissionsCreateEditDeleteSomething = CreateSomething | EditSomething | DeleteSomething,
All = PermissionsCreateEditDeleteSomething | PublishSomething | QueryUsers
}
internal class Program
{
private static void Main(string[] args)
{
IPrincipal admin = Create("james", "admin");
PermissionsManager.GetUserPermissions(admin).ShouldBeEquivalentTo(Permissions.All);
admin.HasPermission(Permissions.None).Should().BeTrue();
admin.HasPermission(Permissions.EditSomething).Should().BeTrue();
admin.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeTrue();
admin.HasPermission(Permissions.PublishSomething).Should().BeTrue();
admin.HasPermission(Permissions.QueryUsers).Should().BeTrue();
admin.HasPermission(Permissions.All).Should().BeTrue();
IPrincipal editor = Create("susan", "editor", "staff");
editor.HasPermission(Permissions.None).Should().BeTrue();
editor.HasPermission(Permissions.EditSomething).Should().BeTrue();
editor.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeTrue();
editor.HasPermission(Permissions.QueryUsers).Should().BeTrue();
editor.HasPermission(Permissions.PublishSomething).Should().BeTrue();
editor.HasPermission(Permissions.All).Should().BeTrue();
IPrincipal staff = Create("michael", "staff");
staff.HasPermission(Permissions.None).Should().BeTrue();
staff.HasPermission(Permissions.EditSomething | Permissions.DeleteSomething).Should().BeTrue();
staff.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeTrue();
staff.HasPermission(Permissions.QueryUsers).Should().BeTrue();
staff.HasPermission(Permissions.PublishSomething).Should().BeFalse();
staff.HasPermission(Permissions.All).Should().BeFalse();
IPrincipal user = Create("bob", "user");
user.HasPermission(Permissions.None).Should().BeTrue();
user.HasPermission(Permissions.EditSomething).Should().BeFalse();
user.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeFalse();
user.HasPermission(Permissions.QueryUsers).Should().BeTrue();
user.HasPermission(Permissions.PublishSomething).Should().BeFalse();
user.HasPermission(Permissions.All).Should().BeFalse();
IPrincipal anon = Create("anonymous");
anon.HasPermission(Permissions.None).Should().BeTrue();
anon.HasPermission(Permissions.EditSomething).Should().BeFalse();
anon.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeFalse();
anon.HasPermission(Permissions.QueryUsers).Should().BeFalse();
anon.HasPermission(Permissions.PublishSomething).Should().BeFalse();
anon.HasPermission(Permissions.All).Should().BeFalse();
Console.WriteLine("All tests passed");
Console.ReadLine();
}
private static IPrincipal Create(string name, params string[] roles)
{
return new GenericPrincipal(new GenericIdentity(name), roles);
}
}