首页 文章

.NET中的身份验证,授权,用户和角色管理以及一般安全性

提问于
浏览
31

我需要知道如何为C#应用程序实现一般安全性 . 在这方面我有什么选择?如果满足我的需求,我宁愿使用现有的框架 - 我不想重新发明轮子 .

我的要求如下:

  • 通常的用户名/密码验证

  • 管理用户 - 为用户分配权限

  • 管理角色 - 将用户分配给角色,为角色分配权限
    根据用户名和角色对用户进行

  • 授权

我正在寻找一个由.Net社区进行时间处理和使用的免费/开源框架/库 .

我的应用程序采用客户端/服务器方法,服务器作为Windows服务运行,连接到SQL Server数据库 . 客户端和服务器之间的通信将通过WCF进行 .

另一件重要的事情是,我需要能够为查看/更新/删除特定实体分配特定用户或角色权限,无论是客户还是产品等 . 杰克可以查看10个客户中的3个,但只更新微软,雅虎和谷歌客户的详细信息,并且只能删除雅虎 .

7 回答

  • 0

    对于粗粒度安全性,您可能会发现内置的主体代码很有用;用户对象(及其角色)由“主体”在.NET中控制,但有用的是运行时本身可以强制执行此操作 .

    委托人的实现可以是实现定义的,你通常可以注入自己的; for example in WCF .

    要查看运行时强制执行粗略访问(即可以访问哪些功能,但不限于哪些特定数据):

    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...");
        }
    }
    

    但是,这对细粒度访问没有帮助(即“Fred可以访问客户A而不访问客户B”) .


    额外;当然,对于细粒度,您可以通过检查主体上的 IsInRole 来简单地在运行时检查所需的角色:

    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;
    }
    

    您还可以编写自己的主体/身份对象来执行角色的延迟测试/缓存,而不必事先了解它们:

    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
        }
    }
    
  • 3

    看看ASP.NET's Membership Providers . 我很难轻易推出自己的提供商 .

  • 1

    我的答案可能取决于这个问题的答案: Is this an Enterprise application which lives within a network with Active Directory?

    如果答案是肯定的,那么这些是我将提供的步骤:

    1)为您的应用程序创建全局组,在我的情况下,我有一个APPUSER组和一个APPADMIN组 .

    2)能够以混合认证模式访问您的SQL Server,然后将您的APPUSER组作为SQL SERVER LOGIN分配给您的数据库,并具有对您的数据库的相应CRUD权限,并确保您访问连接字符串中带有 Trusted Connection = True 的SQL SERVER .

    此时,您的AD商店将负责身份验证 . 因为,您通过TRUSTED CONNECTION访问应用程序,它将把运行应用程序的任何帐户的身份传递给SQL Server .

    现在,对于AUTHORIZATION(即告诉您的应用程序允许登录用户做什么),只需查询AD以获取登录用户所属的组列表即可 . 然后检查相应的组名称并以此方式基于成员身份构建UI .

    我的应用程序的工作方式是:

    • 启动应用程序,凭据基于登录用户,这是身份验证的主要方面(即,他们可以登录,因此它们存在)

    • 我获取有关Windows身份的所有组

    • 我检查标准用户组 - 如果该组不存在所涉及的Windows身份,那么这是一个身份验证失败

    • 我检查了ADMIN用户组 - 在用户组中存在此用户组时,我修改了UI以允许访问管理组件

    • 显示用户界面

    然后我有一个PRINCIPLE对象和确定的权限/ etc,或者我利用GLOBAL变量,我可以访问以确定构建我的表单时适当的UI(即如果我的用户不是ADMIN组的成员,那么我'隐藏所有DELETE按钮) .

    为什么我建议这个?

    这是一个部署问题 .

    根据我的经验,大多数企业应用程序都是由网络工程师而不是程序员部署的 - 因此,认证/授权是AD的责任是有道理的,因为这是网络人员在您讨论时所采用的方式认证/授权 .

    此外,在为网络创建新用户期间,网络工程师(或负责创建新网络用户的任何人)更容易记住在IN AD中执行组分配而不是他们必须进入的事实 . 十几个应用程序来解析授权的分配 .

    这样做有助于获得新员工需要被授予的权限和权限的迷宫,或者需要拒绝离开公司的权限,并且在其所属的中央存储库中维护身份验证和授权(即在AD @域控制器级别) .

  • 33

    我会看看像CSLA.net这样的东西:Expert C# 2008 Business Objects

    它应该提供您需要的一切 .

  • 2

    WCF具有丰富的安全相关功能,提供授权和身份验证 . 详情请见:http://msdn.microsoft.com/en-us/library/ms735093.aspx

  • 0

    我认为你在这里看到一些单独的问题 - 大多数安全系统将认证和授权分开并不是偶然的 .

    对于身份验证,更大的问题是后勤问题 . 或者,这些用户是否有合理的居住地点,无论是本地应用程序,还是Active Directory,某些其他LDAP存储,甚至是其他应用程序 . 究竟在哪里非常重要 - 我们只需要能够稳固地识别用户,并且最好让这个任务成为别人的问题 . 一天结束时,你真的只需要一个唯一的标识符,而来自Accounting的Bob实际上是来自会计的Bob .

    授权是这里问题中更有趣的部分 . 我认为,如果真的是细粒度的,那么无论用户来自哪里,您都希望在您的应用程序中完全管理它 . Marc Gravell确实打造了至少模拟其中一些的好方法 - 使用IPrincipal和PrincipalPermission的一些自定义实现来管理事物是一种非常干净的入门方式 . 除此之外,您可以使用像this one这样的技术以相当干净的方式做出更复杂的授权决策 .

  • 3

    我会使用术语 - 'RBAC'(基于角色的访问控制系统)作为您所有要求的解决方案 .

    我不会在这里详细解释'RBAC',而是我会简要介绍一下 .

    它基本上包含3个功能 .

    1)身份验证 - 确认用户的身份 . 通常通过用户帐户和密码或凭据来完成 .

    2)授权 - 它定义了用户在应用程序中可以做什么和不能做什么 . 防爆 . 允许“修改订单”,但不允许“创建新订单” .

    3)审核用户对应用程序的操作 . - 它跟踪用户对应用程序的操作,以及谁已授予哪些用户访问权限?

    你可以在wiki上查看RBAC .

    https://en.wikipedia.org/wiki/Role-based_access_control

    现在,关于满足您的要求 - 可能的解决方案之一是根据需要扩展Asp.Net成员资格 .

    关于一些准备使用的框架,我建议VisualGuard为我工作,你应该检查一下,它完成所有你需要的东西非常容易,最重要的是,它管理你的所有用户,角色,权限通过管理中心控制台和应用程序,并且为了定义权限,管理员不需要开发人员的知识,即他/她可以通过UI创建对活动的限制 .

    您还可以查看本文以更好地了解基于权限和角色的系统 .

    http://www.visual-guard.com/EN/net-powerbuilder-application-security-authentication-permission-access-control-rbac-articles/dotnet-security-article-ressources/role-based-access-control-source_soforum.html

相关问题