【问题标题】:ASP.NET Membership & Role-based SecurityASP.NET 成员资格和基于角色的安全性
【发布时间】:2011-11-03 08:30:15
【问题描述】:

我正在使用ASP.NETC# 开发一个博客引擎。主要解决方案由以下几个项目组成

  • DomainModel:存储库的域实体和接口
  • AppService:应用服务、视图模型映射器、消息等。
  • Repositories:EF 存储库、XML 存储库、存根存储库
  • Presentation :实现 MVP 模式(视图、演示者、接口)

用户端项目目前是WebForms web 应用程序,项目快完成了。最后一件事是将整个系统与ASP.NET Membership 集成。有两件事需要考虑。

首先,在博客数据库的会员数据库中只需要一个用户帐户ID。 最后,必须在 UI 项目中实现基于角色的安全性。因为我对分布式应用程序开发、DDD 和其他东西还很陌生,所以我想知道基于角色的安全性的实现是否仅仅是 UI 应用程序的责任,或者还有其他事情需要处理解决方案的层数。据我目前所知,只有视图(网页)必须实现基于角色的安全性并根据当前会话呈现不同的内容并提供不同的功能。但仅此而已吗?

我知道这可能是一个通用问题,当然实施和设计会根据项目需求而有所不同。但是,如果在分布式/分层应用程序中实现基于角色的安全性和表单身份验证时要遵循一般的经验法则,那么事先了解它们会很棒。例如:

  • 安全实施是否只是 UI 应用的责任?
  • 我能否调整/更改我的域模型和/或其他层的设计,以便更轻松地实施基于角色的安全性,而不是完全依赖 UI 应用程序。
  • 在其他层中考虑安全性是否是个好主意,以便 UI 层只是数据的表示以及用户和系统之间的媒介。

【问题讨论】:

    标签: .net asp.net asp.net-membership domain-driven-design n-tier-architecture


    【解决方案1】:

    在解决这个问题一段时间后,我得出了以下结论。

    用户体验层中实现AuthenticationRole-based securityAuthorization等安全并不是一个好主意,主要有两个原因:

    1. 如果您想为您的应用程序创建其他 UI,例如 WinFormsSilverlight UI,那么您将不得不从头开始重新实现此安全性。
    2. 您始终可以使用系统的其他组件/层,而无需创建 UI 应用程序。假设您创建了一个简单的控制台应用程序,它引用了系统中的其他层(即Repositories)。然后您可以实例化存储库并操作数据。在这种情况下,您已成功覆盖任何安全性。

    因此,解决方案是在嵌入域模型本身且不绑定到用户体验层 (UI) 的另一层中实现这种安全性。

    现在,您可能会采取一些不同的方式来解决这个问题。假设我们有一个名为AppService 的层,它是整个系统的入口点。该层由消息(类似于Request-Response 模式的消息模式)、ViewModels(域实体的平面视图)和Methods for retrieving and manipulating data 等组成。在这里,我们可以借助PrincipalPermission 对象来实施此类安全措施。我们可以将安全规则应用于类和方法。这是一个简单的例子:

    [PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
    public void DoSomething()
    { }
    

    使用为此方法定义的属性,代码要求对调用者进行身份验证。认证模型可以是任何东西,包括Windows AuthenticationForms Authentication等等。现在这工作正常,因为现在我们已经将 UI 与服务层中定义的安全规则松散耦合。但是还有一个问题。

    只要服务层确实是系统的主要入口点,这种设计就可以正常工作。这意味着如果您仍然可以实例化,比如存储库,不需要获取您的 AppService 的实例,您仍然可以覆盖安全规则。话虽如此,您必须以这样一种方式设计域模型,即使用系统的组件/层需要 AppService 的实例。

    在这种情况下,系统中提供的任何功能都只能通过应用服务层访问。另一方面,如果这是不可能的,或者目前不值得关注,您还必须在其他层中定义您的安全规则。这意味着您也必须在存储库中定义安全规则。因此,如果有人实例化了一个存储库并试图操作数据,但没有通过UIAppService 层执行他的命令,您仍然可以执行安全措施。

    另一件事是,在您的类和方法上使用PrincipalPermission 规则并不依赖于特定的身份验证/授权模型。因此,您可以在带有Forms Authentication 的Web 应用程序或带有Windows/AcctiveDirectory Authentication 的Windows 应用程序中使用此类安全规则。

    您还记得,我正在ASP.NET 开发一个简单的博客引擎,这个模型目前运行良好。如果有更详细的深入利弊,或者示例和博客文章可以帮助解决这个主题,请确保发布您的 cmets 和答案 [:

    【讨论】:

      【解决方案2】:

      安全性是一个跨领域的关注点:涉及 UI、应用程序和域层。我的理解是您处理诸如“只有作者可以编辑博客”或“只有注册用户可以评论”之类的规则。在这种情况下,UI 应该了解这些规则来决定是呈现“编辑”还是“评论”链接。域对象应该能够强制执行这些规则。

      据我所知,ASP.NET Membership 做了很多事情,包括用户存储、身份验证、授权和角色管理。但是它不知道您的域。它不知道博客是什么。它知道什么是 ASP Page。因此,如果您不想将域规则表示为页面访问规则,则可能需要在应用程序和 ASP.NET 成员资格之间划一条粗线。您可能希望将用户存储和身份验证委托给 ASP.NET,但您自己完成其余的工作。在您的域模块中不直接依赖 ASP.NET 可能也是一个好主意。如果您以后决定从 Web 窗体切换到 MVC,或者您是否将为您的博客引擎提供 Web API,您还需要考虑 ASP.NET Membership 将如何工作。

      【讨论】:

        【解决方案3】:

        安全应该是所有应用程序的责任。这实际上取决于您的应用的结构。

        我的观点是所有层级都应该有一些参与。安全性应该是其他服务可以使用的另一项服务。这样您就可以访问所有级别的安全模型。如果用户未经授权,管理 UI 可以立即阻止用户,但表示数据检索服务可以检查其检索的对象对当前用户是否有效。

        如果您想以其他方式使用您的数据模型,例如通过 Web 服务或其他应用程序(例如 Silverlight),您也可以通过这种方式获得好处。

        更新

        所有层都确实需要注意安全性,因为所有层都需要在某个时候触及它。 UI 需要它,以便它可以打开和关闭 UI 元素。服务需要意识到这一点,以确保他们正在执行的操作对当前用户等有效。

        安全性真的不应该是您在项目结束时想到的事情,只需打开即可。它应该是在所有级别的应用程序中设计的。

        如何实现它取决于您编写应用程序的方式。我想说最好的方法是在你的应用程序和 asp 成员之间有一个抽象层。您可以获得您已经知道的所有好处,例如测试、重新架构等

        您可能要考虑的一件事是权利或许可的概念。 ASP 没有用于处理此问题的本地库,因此您必须自己开发。每当您想做某事时,请检查用户是否有权。这些权限可以滚动到角色中,而角色又可以分配给用户或用户组。您可以细粒度地控制用户可以执行的操作,并且将来可以轻松添加新角色。

        【讨论】:

        • 只是为了确保我理解这一点,如果安全可以是另一个服务,那么只有我的AppService 层需要引用和使用这个服务层,对吗?另外,您能否提供示例/链接或多谈谈我如何编写此类安全服务以便其他层可以使用它。最后,如果要在另一个服务层实现安全性,那么 MVP 模式和我的 Web 表单应该如何与这个服务层集成?
        【解决方案4】:

        不确定您究竟追求什么,但值得注意的是标准 PrincipalPermissionAttribute Class 可以很好地与使用此提供程序技术实现的 ASP.NET 角色配合使用。

        这意味着您可以使用代码访问安全性和声明性属性来确保您的 API/域/方法只能由特定角色的用户访问。所以是的,您可以使用 ASP.NET 成员身份在 UI 层之外强制执行安全性。

        【讨论】:

        • 仅在 UI 应用程序中实现安全性不是更容易,因此未经授权的调用甚至无法到达其他层吗?我的理解是这样应该更容易,但是如果可以在 UI 应用程序中覆盖这种类型的安全性,那么是的,其他层也必须了解一些安全规则[?]
        • @Nexus - 事实上,你可以两者兼得。您可以在域/业务层上添加属性,也可以在 UI 层中使用它。这取决于您需要的安全级别。 “更容易”这个词通常不适合“更安全”:-)
        • 所以code access security attributes 在其他层中的域对象和方法的组合,以及在 UI 层中呈现不同内容的能力可以正常工作。顺便说一句,西蒙,在每个方法/服务的AppService 层中检查当前会话是否是authenticated/authorized 是个好主意吗?这可以在另一个服务层的帮助下完成。毕竟,AppService 层是整个系统的入口点,用户只会与该层进行交互。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-18
        • 2011-02-03
        • 1970-01-01
        • 2010-12-28
        • 1970-01-01
        • 2010-09-17
        • 1970-01-01
        相关资源
        最近更新 更多