nTier 应用程序中的 .Net 会员资格

发布于 2024-08-04 23:39:41 字数 882 浏览 0 评论 0原文

假设我有一个 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;
   }

如果执行此操作,我将必须在两个层中引用并实例化成员身份类。这是构建这样的应用程序的正确方法吗?看起来有很多冗余。

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

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

Lets say I have an ASP.Net MVC App and this app (UI) references a Business Logic Layer (BLL) and the BLL references my Data Access Layer (DAL).

I am utilizing a Custom Membership and Role provider for Authorization.

I am trying to determine what layers need to reference my Membership provider.

In MVC you can perform Authorization checks in the following manner:

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

And in my BLL I may want to check to see if a User is in a Role as well:

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

I would have to reference and instantiate the Membership classes in both layers if I do this. Is this the correct way to architect an app like this? Seems like a lot of redundancy.

Since I have a BLL do I avoid using the "[Authorize(Roles = "SomeRoleName")]" attributes and instead call a BLL function from within the MVC code to check if the user is in a role? If I do this the MVC still needs a reference to the membership provider for authentication and such anyway to take advantage of the Login and other ASP controls, right?

Am I way off base and heading in the wrong direction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

楠木可依 2024-08-11 23:39:41

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

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

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

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

In my view this is a weakness of the Membership/Role design.

The way I would get round this, for example to have role-based authorization on both UI and BLL tiers in a distributed n-tier app, would be to expose a service in the BLL tier that exposes the relevant bits (GetRolesForUser etc) and is implemented by calling the RoleProvider on the server.

Then implement a custom RoleProvider on the client that is implemented by calling the service exposed by the BLL.

In this way the UI tier and BLL tier both share the same RoleProvider. The UI tier can use knowledge of the current user's roles to improve the UI (e.g. hiding/disabling UI controls corresponding to unauthorized features), and the BLL can ensure that users can not execute
business logic for which they are not authorized.

心如荒岛 2024-08-11 23:39:41

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

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

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

希望这会有所帮助。

Excellent question, I asked myself the same thing today. One of the idea I had (but I'm not really sure if it's the best way to go) is to use a interface (ex: IRoleProvider) that you can pass to your BLL to test your access.

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

With this, you still verify your access in your BLL, you can use a mock in your unit tests to check your logic and you just need to create a class (or implement this in a baseController class) in your MVC web site that will implement IRoleProvider and do the proper check using ASP.NET authorization API.

Hope this will help.

雪落纷纷 2024-08-11 23:39:41

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

尽管是 3 年前写的关于城堡的文章,这篇文章可能有帮助。中途开始涉及 IPrincipal 的内容。

HTHS
查尔斯

Get your User object to implement the IPrincipal interface and throw that around the layers. Then you can still use the built in [Autorize] attribute.

Athough written over 3 years ago and about castle, this article may help. It starts getting into the IPrincipal stuff half way down.

HTHS
Charles

鼻尖触碰 2024-08-11 23:39:41

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

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

例子:

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

Why not pass the roles into your BLL so that you do not have any dependency on Membership. Or use an interface like MartinB suggested.

What happens in the future when your stake holder(s) decide to go with a different form of authentication and you no longer work with a Role object?

Example:

IsRoleEditor(User user, string[] roles)
{
  return roles.Contains("ModifyRoles");
}
简美 2024-08-11 23:39:41

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

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

戴维

Are you not missing the point of MVC. MVC splits out naturaly into tiers. Model (DAL), controller (BLL), View (Presentation). These can go in different projects if you like but as the controller has all the business logic - you only need to access the RoleProvider there.

Then apply patterns such as the repository, pattern etc to split out further if you want.

Davy

橘寄 2024-08-11 23:39:41

调用 MVC 控制器“UI”是完全没有意义的。MVC 中的“C”是 BLL 的一部分,即使它引用了将调用的类BLL。不过,这不是你问题的重点。

我想我可以通过问这个问题来解决这个问题:“你的‘UI’应用程序和你的‘BLL’是否真的需要 100% 分离?”。如果两个组件共享对成员/角色提供者的依赖关系,那么就让它如此并开始工作。

如果您拔掉 BLL 并插入新的 BLL,也许您可​​以接受对 .NET 提供程序的共享依赖。您知道这可能没问题,您的应用程序可能不会崩溃。

我认为乔上面的回答很有道理......

To call the MVC controller 'UI' is way off the mark.. The 'C' in MVC is part of your BLL, even if it references classes that you would call the BLL. However, that is not the point of your question.

I think I would solve this problem by asking the question, "is there a real requirement for 100% separation of your 'UI' app and your 'BLL'?". If both components share a dependency on the member/role providers, then let it be so and get to work.

In the case where you unplug your BLL and plug in a new one, perhaps having a shared dependency on a .NET provider is something you can live with. You know that is probably ok and your app just might not fall apart.

I think Joe's answer above makes much sense though...

野稚 2024-08-11 23:39:41

我认为你所做的很好。

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

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

将 MVC 会员资格提供程序隐藏在界面后面会很好,这样您就可以将其替换为 WinForms 会员资格提供程序(例如),并且能够对您的控制器进行单元测试。

I think what you are doing is fine.

The authorisation and authentication should live within a services layer, that is perhaps passed into your controllers.

If the controller sets the Principal and Identity and you then use that in the controller through the use of the MVC attributes then it sounds like a good idea.

It would be nice to hide your MVC Membership provider behind an interface, that way you can swap it out for a WinForms Membership provider (for example) and would be able to unit test your controllers.

终遇你 2024-08-11 23:39:41

角色访问通常不应位于 BLL 中。访问是用户界面的责任。

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

Thread.CurrentPrincipal

Role access normally shouldn't be in the BLL. Access is a user interface responsibility.

With that said, leverage the IPrinciple interface as the above posters have stated. You have access to IPrinciple at the Thread level.

Thread.CurrentPrincipal
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文