32

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

我的要求如下:

  • 通常的用户名/密码认证
  • 用户管理 - 为用户分配权限
  • 角色管理 - 将用户分配给角色,将权限分配给角色
  • 基于用户名和角色的用户授权

我正在寻找一个经过时间考验并被 .Net 社区使用的免费/开源框架/库。

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

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

4

7 回答 7

35

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

主体的实现可以是实现定义的,您通常可以注入自己的;例如在 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
    }
}
于 2009-08-09T08:54:36.893 回答
3

查看ASP.NET 的 Membership Providers。我认为开箱即用的 SQLMembershipProvider 不适用于您的情况,但很容易推出您自己的提供程序。

于 2009-08-03T15:38:44.380 回答
3

我的回答可能取决于对这个问题的回答:这是一个存在于 Active Directory 网络中的企业应用程序吗?

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

1)为您的应用程序创建全局组,在我的例子中,我有一个 APPUSER 组和一个 APPADMIN 组。

2) 让您的 SQL Server 能够在 MIXED AUTHENTICATION 模式下访问,然后将您的 APPUSER 组作为 SQL SERVER LOGIN 分配给您的数据库,并对您的数据库具有适当的 CRUD 权限,并确保您访问连接字符串中具有Trusted Connection = True的 SQL SERVER 。

此时,您的 AD 商店将负责身份验证。由于您通过可信连接访问应用程序,因此它将运行应用程序的任何帐户的身份传递给 SQL Server。

现在,对于 AUTHORIZATION(即告诉您的应用程序允许登录用户做什么),只需向 AD 查询登录用户所属的组列表即可。然后检查适当的组名并以这种方式基于成员资格构建您的 UI。

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

  1. 启动应用程序,凭据基于登录用户,这是身份验证的主要方面(即他们可以登录,因此他们存在)
  2. 我得到所有组的 Windows 身份有问题
  3. 我检查标准用户组——如果该组不存在用于所讨论的 Windows 身份,那么这就是身份验证失败
  4. 我检查 ADMIN 用户组——在用户组中存在此用户组的情况下,我修改 UI 以允许访问管理组件
  5. 显示用户界面

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

我为什么建议这个?

这是部署的问题。

根据我的经验,大多数企业应用程序是由网络工程师而不是程序员部署的——因此,将身份验证/授权作为 AD 的责任是有道理的,因为当您讨论身份验证/授权时,网络人员会去那里。

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

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

于 2009-08-10T20:14:15.383 回答
2

我会看一下 CSLA.net:Expert C# 2008 Business Objects之类的东西

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

于 2009-08-03T15:40:02.583 回答
1

WCF 具有丰富的安全相关功能,提供授权和身份验证。详细信息在这里:http: //msdn.microsoft.com/en-us/library/ms735093.aspx

于 2009-08-03T15:35:53.777 回答
0

我认为您在这里看到了一些单独的问题——大多数安全系统将身份验证和授权分开并不是偶然的。

对于身份验证,更大的问题是后勤问题。或者,这些用户是否存在逻辑上的位置,无论是应用程序本地、Active Directory、其他 LDAP 存储还是其他应用程序。确切的位置是无关紧要的——我们只需要能够可靠地识别用户,并且最好让这个任务成为别人的问题。一天结束时,您真的只需要一个唯一的标识符,并且让来自会计的 Bob 实际上是来自会计的 Bob 感到舒适。

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

于 2009-08-10T20:27:01.223 回答
0

我会使用“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

于 2015-10-08T09:35:16.437 回答