且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

身份验证,授权,用户和角色枭雄和.NET一般安全

更新时间:2023-09-20 14:43:10

有关粗粒度的安全性,你可能会发现内置的本金code有用的;用户对象(和他们的角色)在.NET中的委托人控制,但有效的运行时本身可以强制这一点。

For coarse-grained security, you might find the inbuilt principal code useful; the user object (and their roles) are controlled in .NET by the "principal", but usefully the runtime itself can enforce this.

主要的实现可以实现定义,并且通常可以注入自己的; 例如在WCF

The implementation of a principal can be implementation-defined, and you can usually inject your own; for example in WCF.

要看到运行时强制粗接入(即其中的功能的可以被访问,但不限于哪个特定的数据的):

To see the runtime enforcing coarse access (i.e. which functionality can be accessed, but not limited to which specific data):

static class Roles {
    public const string Administrator = "ADMIN";
}
static class Program {
    static void Main() {
        Thread.CurrentPrincipal = new GenericPrincipal(
            new GenericIdentity("Fred"), new string[] { Roles.Administrator });
        DeleteDatabase(); // fine
        Thread.CurrentPrincipal = new GenericPrincipal(
            new GenericIdentity("Barney"), new string[] { });
        DeleteDatabase(); // boom
    }

    [PrincipalPermission(SecurityAction.Demand, Role = Roles.Administrator)]
    public static void DeleteDatabase()
    {
        Console.WriteLine(
            Thread.CurrentPrincipal.Identity.Name + " has deleted the database...");
    }
}

不过,这不符合细粒度访问帮助(即弗雷德可访问客户A,但没有客户B)。

However, this doesn't help with the fine-grained access (i.e. "Fred can access customer A but not customer B").


附加;当然,细粒度的,你可以简单地检查所需的角色在运行时,通过检查 IsInRole 的本金:

Additional; Of course, for fine-grained, you can simply check the required roles at runtime, by checking IsInRole on the principal:

static void EnforceRole(string role)
{
    if (string.IsNullOrEmpty(role)) { return; } // assume anon OK
    IPrincipal principal = Thread.CurrentPrincipal;
    if (principal == null || !principal.IsInRole(role))
    {
        throw new SecurityException("Access denied to role: " + role);
    }
}
public static User GetUser(string id)
{
    User user = Repository.GetUser(id);
    EnforceRole(user.AccessRole);
    return user;
}

您也可以编写自己的委托人/身份对象做角色懒测试/缓存,而不必知道所有这些前期:

You can also write your own principal / identity objects that do lazy tests / caching of the roles, rather than having to know them all up-front:

class CustomPrincipal : IPrincipal, IIdentity
{
    private string cn;
    public CustomPrincipal(string cn)
    {
        if (string.IsNullOrEmpty(cn)) throw new ArgumentNullException("cn");
        this.cn = cn;
    }
    // perhaps not ideal, but serves as an example
    readonly Dictionary<string, bool> roleCache =
        new Dictionary<string, bool>();
    public override string ToString() { return cn; }
    bool IIdentity.IsAuthenticated { get { return true; } }
    string IIdentity.AuthenticationType { get { return "iris scan"; } }
    string IIdentity.Name { get { return cn; } }
    IIdentity IPrincipal.Identity { get { return this; } }

    bool IPrincipal.IsInRole(string role)
    {
        if (string.IsNullOrEmpty(role)) return true; // assume anon OK
        lock (roleCache)
        {
            bool value;
            if (!roleCache.TryGetValue(role, out value)) {
                value = RoleHasAccess(cn, role);
                roleCache.Add(role, value);
            }
            return value;
        }
    }
    private static bool RoleHasAccess(string cn, string role)
    {
        //TODO: talk to your own security store
    }
}