【问题标题】:.Net Membership in nTier AppnTier 应用程序中的 .Net 成员资格
【发布时间】:2010-11-27 07:44:52
【问题描述】:

假设我有一个 ASP.Net MVC 应用程序,该应用程序 (UI) 引用了业务逻辑层 (BLL),而 BLL 引用了我的数据访问层 (DAL)。

我正在使用自定义成员资格和角色提供程序进行授权。

我正在尝试确定哪些层需要引用我的会员资格提供者。

在 MVC 中,您可以通过以下方式执行授权检查:

[Authorize(Roles = "SomeRoleName")]
public ActionResult Index()
{
//do something
}

在我的 BLL 中,我可能想检查用户是否也处于角色中:

public static bool IsRoleEditor(User user, Role userRole)
  {
   bool retValue = false;

   if (user.Application.AppID == UserRole.Application.AppID)
   {
        if (Roles.IsUserInRole("ModifyRoles"))
        {
           retValue = true;
        }


    return retValue;
   }

如果我这样做,我将不得不在两个层中引用和实例化 Membership 类。这是构建这样的应用程序的正确方法吗?似乎有很多冗余。

由于我有 BLL,我是否应避免使用“[Authorize(Roles = "SomeRoleName")]”属性,而是从 MVC 代码中调用 BLL 函数来检查用户是否处于角色中?如果我这样做,MVC 仍然需要对成员资格提供程序的引用以进行身份​​验证,并且无论如何都要利用登录和其他 ASP 控件,对吗?

我是否偏离了基地并朝着错误的方向前进?

【问题讨论】:

    标签: .net asp.net-mvc asp.net-membership n-tier-architecture


    【解决方案1】:

    我认为你正在做的很好。

    授权和身份验证应该存在于服务层中,这可能会传递到您的控制器中。

    如果控制器设置了 Principal 和 Identity,然后您通过使用 MVC 属性在控制器中使用它,那么这听起来是个好主意。

    最好将 MVC Membership 提供程序隐藏在接口后面,这样您就可以将其换成 WinForms Membership 提供程序(例如),并且能够对您的控制器进行单元测试。

    【讨论】:

      【解决方案2】:

      调用 MVC 控制器“UI”是不合时宜的。MVC 中的“C”是 BLL 的part,即使它引用了 的类> 会调用 BLL。但是,这不是您的问题的重点。

      我想我可以通过提出以下问题来解决这个问题:“真的需要 100% 分离您的 'UI' 应用程序和您的 'BLL' 吗?”。如果两个组件共享对成员/角色提供者的依赖关系,那么就让它继续工作吧。

      在您拔下 BLL 并插入新的 BLL 的情况下,您可能可以忍受对 .NET 提供程序的共享依赖。您知道这可能没问题,而且您的应用可能不会崩溃。

      我认为乔上面的回答很有意义......

      【讨论】:

      • 不确定控制器是你的 BLL 的一部分,事实上,我认为它不应该包含任何业务逻辑,只是你的域对象之间的编排。
      • WTF 是业务逻辑吗?整个应用程序是业务逻辑,由业务逻辑的各种组件组成.. 逻辑的 UI 部分,逻辑的 MVC 部分.. 正确地架构和抽象代码是目标,而不是为复杂的组件应用通用名称.这些直线上下线性层的想法是愚蠢的。解决方案图是对象的复杂映射,处理交叉是我们的工作-杰伊的问题是一个很好的问题,处理依赖关系中的交叉将是一项有趣的任务..我仍然认为乔的回答最有意义,现在我只是在咆哮。
      【解决方案3】:

      您是否没有错过 MVC 的重点。 MVC 自然地分成几层。模型(DAL)、控制器(BLL)、视图(演示)。如果您愿意,这些可以放在不同的项目中,但由于控制器具有所有业务逻辑 - 您只需要访问 RoleProvider 那里。

      然后,如果需要,可以应用存储库、模式等模式来进一步拆分。

      戴维

      【讨论】:

      • 我了解 MVC 的概念,但是如果我将 BLL 设置为包含角色验证,那么为什么要在 UI 中使用“[Authorize(Roles = "SomeRoleName")]”功能?跨度>
      • @jay 控制器中使用了 Authorize 属性,正如 Davy 所说,这将是业务层。我认为他的意思是你似乎忽略了“层”已经被 MVC 模式分割的事实。我认为这完全取决于你如何重新构建这个解决方案 Jay,你能做一个图表来向我们展示你是如何设计这个的吗?
      • 图表会有所帮助。您是指视图中的 UI 功能吗?如果你这样做了,我认为只有愚蠢的 HTML 很好,但你可能有一个视图,你想根据角色显示一些东西,比如只有主管才能在其他共享视图中看到的“授权复选框”。因此,在我看来,能够在这里访问角色很有用。
      【解决方案4】:

      在我看来,这是会员/角色设计的一个弱点。

      我解决这个问题的方法,例如在分布式 n 层应用程序中的 UI 和 BLL 层上具有基于角色的授权,将在 BLL 层中公开一个服务,该服务公开相关位 (GetRolesForUser等),并通过调用服务器上的 RoleProvider 来实现。

      然后在客户端实现一个自定义的RoleProvider,通过调用BLL暴露的服务来实现。

      这样,UI 层和 BLL 层都共享同一个 RoleProvider。 UI 层可以使用当前用户角色的知识来改进 UI(例如隐藏/禁用与未经授权的功能对应的 UI 控件),并且 BLL 可以确保用户无法执行 未经授权的业务逻辑。

      【讨论】:

        【解决方案5】:

        为什么不将角色传递到您的 BLL 中,这样您就不会依赖于成员资格。或者使用像 MartinB 建议的界面。

        当您的利益相关者决定采用不同形式的身份验证并且您不再使用 Role 对象时,将来会发生什么?

        例子:

        IsRoleEditor(User user, string[] roles)
        {
          return roles.Contains("ModifyRoles");
        }
        

        【讨论】:

          【解决方案6】:

          角色访问权限通常不应该在 BLL 中。访问是用户界面的责任。

          话虽如此,如上述海报所述,利用 IPrinciple 界面。您可以在线程级别访问 IPrinciple。

          Thread.CurrentPrincipal
          

          【讨论】:

          • 查尔斯,谢谢您的回复。正如您所看到的,尽管我必须处理一些业务逻辑,而不是基本角色检查,才能确定用户真正的安全性。我认为所有 BL 都应该在 BLL 中,这就是为什么我也计划在那里封装安全性。您是说上面的“IsRoleEditor”最好驻留在我的 UI 层而不是 BLL 中?
          • -1 我不同意:授权(无论是角色访问还是其他机制)绝对是 BLL 的责任。 UI 层可能在客户端(例如 Winforms)上运行,因此可能会受到攻击。
          • 这完全取决于您如何设计此应用程序。给我们一个你的解决方案的例子,一些简单的项目名称以及它们如何相互引用。
          • @Joe 我不同意你的观点。将授权放入 BLL pidgon 会使您在整个应用程序及其视图中使用该授权实现。假设 Web 服务、Win Forms、Web Forms、REST API 等……都必须具有相同的授权。这个想法充满了问题。考虑使用 AD(活动目录)。 AD 适用于 WinForms,但不适用于任何 Web。如果必须在 BLL 中使用授权,我会将其包围在一个抽象中,可能是提供者模式。
          • 查尔斯在这里说得通。你不能指望 BLL 能神奇地做所有事情。应用程序是所有这些组件,每个组件都有自己的安全要求。包括 UI、“BLL”、数据库、服务器以及您调用的任何 Web 服务。
          【解决方案7】:

          很好的问题,我今天问自己同样的问题。我的一个想法(但我不确定这是否是最好的方法)是使用可以传递给 BLL 的接口(例如:IRoleProvider)来测试您的访问权限。

          public static bool IsRoleEditor(User user, IRoleProvider rp)
          {
               return (rp.IsUserInRole(user,"ModifyRoles"));
          }
          

          这样,您仍然可以在 BLL 中验证您的访问权限,您可以在单元测试中使用模拟来检查您的逻辑,您只需要在 MVC 网站中创建一个类(或在 baseController 类中实现它)这将实现 IRoleProvider 并使用 ASP.NET 授权 API 进行适当的检查。

          希望这会有所帮助。

          【讨论】:

            【解决方案8】:

            获取您的 User 对象以实现 IPrincipal 接口并将其扔到各个层。然后你仍然可以使用内置的 [Autorize] 属性。

            虽然写于 3 年多前关于城堡,this article 可能会有所帮助。它开始在中途进入 IPrincipal 的内容。

            HTHS
            查尔斯

            【讨论】:

            • 一定要使用MVC中的Authorize属性。您无需手动检查 IsInRoles。
            • 问题是除了我认为应该始终在 BLL 中的“IsInRole”或“Authorize”之外,我确实需要处理其他业务逻辑。我可以在任何地方传递用户对象,但是为什么不直接忽略 Authorize 并只使用 BLL。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-06-13
            • 2010-12-23
            • 2012-10-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多