需要了解如何在我的应用程序(ASP.NET MVC3)中管理角色
本文关键字:MVC3 NET ASP 角色 管理 应用程序 了解 我的 | 更新日期: 2023-09-27 18:33:24
我正在开发一些网站,这是一种在线工作场所,会有一些用户和一些正在进行的计算机编程项目,每个用户可以有多个角色,例如一个特定的用户可以是一个项目的项目经理和另一个项目的开发人员。 当然,项目经理在项目中比开发人员拥有更大的权限。 我的问题是如何在我的代码中整齐地管理它?我打算使用我的自定义角色提供程序并为此使用 Authorize 属性,但这还不够,因为我需要项目 ID 加上用户 ID 才能在特定项目中查找用户角色。
首先,您必须为扩展角色管理创建其他表,例如projects
以及与operations
上下文中的users
的关系,这可能是您的controller's actions
。
一种方法是为roles
创建自己的表。在这种情况下,您将仅使用Asp网络membership users
,但这完全取决于您的要求。
其次你必须在MVC
中处理它,在我看来最好的方法是通过你自己的自定义Authorization
属性来实现它,并使用你的自定义授权属性而不是[Authorization]
属性来装饰你的控制器的操作。
它非常简单。
[CustomAuthorize]
//[Authorize]
public ActionResult GetProjectTasks(string projectname)
{
}
为此,您必须从FilterAttribute
固有类,并且还必须实现IAuthorizationFilter
接口。
public void OnAuthorization(AuthorizationContext filterContext)
{
HttpCookie authCookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new GenericPrincipal(identity, new string[] { authTicket.UserData });
filterContext.HttpContext.User = principal;
}
var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var action = filterContext.ActionDescriptor.ActionName;
var user = filterContext.HttpContext.User;
var ip = filterContext.HttpContext.Request.UserHostAddress;
var isAccessAllowed = CustomAuthenticationLogic.IsAccessAllowed(controller, action, user, ip);
if (!isAccessAllowed)
{
// Code if user is authenticated
FormsAuthentication.RedirectToLoginPage();
}
}
在方法 OnAuthorization
中,您可以获取自定义授权逻辑中可能需要的所有信息,如HttpContext
、Controller
名称Action
名称。只需从此方法调用自定义身份验证逻辑。自定义身份验证逻辑可能如下所示。
public class CustomAuthenticationLogic
{
public static bool IsAccessAllowed(string controller, string action, IPrincipal user, string ip)
{
//
// Your custom logic here
//
}
}
我前段时间做了一些研究,可以向你保证:
- ASP.NET 内置功能很可能无济于事(没有办法考虑项目 ID 之类的东西(
- 基于角色的访问模型是最合适的,有不同的方法可以实现它。Rusted 建议的 AzMan 实际上很好,但管理与上下文相关的规则可能很困难。 例如:用户 A 在项目 C 中执行操作 B,而它则说星期日。看看阿兹曼。
- 将访问规则与代码混合在一起是非常糟糕的。您的安全模型不需要与应用程序的工作方式相关(ASP.NET MVC(所以这个是错误的:
var isAllowed = AccessControl.IsAccessAllowed(controller, action, user, ip);
它必须看起来像:
var isAllowed = AccessControl.IsAccessAllowed(user, operation, context);
然后,您可以随时使用它,在每个操作中或将其包装为属性。
其中操作是"登录"、"发布回复"、"阅读主题"等,上下文是其他的,比如你"项目 ID"、"星期几"、"用户 ip"等
有很多东西可以写,比如角色重叠,上下文等。简而言之:谷歌对于".NET 基于角色的访问模型"可能更容易编写小型自定义安全框架。使其与用户、角色、操作和项目 ID 一起使用
操作分配给角色,角色分配给具有已定义项目 ID 的用户,您可以对操作和角色进行硬编码,因此在您的数据库中只有一个小的变化:用户到角色映射
如果您的规则更复杂且属性不够,则可以在控制器中计算用户是否可以访问某些功能,并在 ViewModel 中添加反映对这些功能的访问或无访问权限的属性。
这样,您的视图将非常细,它将根据这些 ViewModel 布尔属性显示内容。
因此,假设您的用户只能读取,您可以有一个属性 bool IsReadOnly,该属性将根据授权规则在控制器中填充,并且该属性将在视图中用于生成标签而不是文本框。
我喜欢 AzMan 的主要思想是针对操作进行编程的概念。
操作是非常精细的东西,在使用上不应该重叠,并且只能由开发人员定义。通过将操作分组为任务,将任务分组到角色,然后将主体(用户和组(映射到角色,你拥有一个非常强大的模型,用于在应用中定义授权。由于您直接对操作进行编程,因此您的代码不需要知道用户具有哪些角色,并且可以由管理员在运行时更改。事实上,有人可以定义一组完全不同的角色来使用您在代码中使用的操作,并且您根本不需要更改任何代码。这才是真正的力量所在。
我的意思不是"在您的应用程序中使用 AzMan"(但也许您应该尝试(。这是一个强大的模型,但它也很复杂,对于简单的事情来说可能有点矫枉过正。如果您只有一个或两个角色,并且它们保护的操作不重叠或不太可能更改,那么它可能没有必要。
我建议您通过扩展内置AuthorizeAttribute
过滤器而不是实现IAuthorizationFilter
接口来创建自定义Authorize
过滤器。内置AuthorizeAttribute
可以完成许多管道工作,可以解决缓存问题和其他问题,如果要实现该接口,则必须完成所有这些工作。
您必须重写 AuthorizeCore
方法,并且您在那里执行所有角色检查逻辑。您必须存储在会话中的user id
,project id
您必须弄清楚。
public override bool AuthorizeCore(HttpContextBase httpContext)
{
}
授权属性源代码 - http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/913d37658a44#src%2fSystem.Web.Mvc%2fAuthorizeAttribute.cs
自定义授权属性示例:http://msdn.microsoft.com/en-us/library/ee707357(v=vs.91(.aspx
根据roles
进行groups
。
然后将不同的用户添加到特定组。可以>组
1) Admin Group
2) Developer Group
3) Project1-QA Group
4) Project2-Manager Group
保存[user - group]
和[group - projects]
的映射,具体取决于您的数据库设计。
您可以根据需要为一个用户设置任意多个角色(组(。
一种非常简单的方法 - 对于站点范围的访问控制,您可以将 INT 列添加到用户表中,并将该 INT 的每个位映射到[flags]
枚举 - 例如 [Flags] enum Access { UpdateProjects, AddProjects }
.
对于每个项目的访问控制,请创建一个名为 ProjectAccessControl 的表,其中包含三列:ProjectID(项目表的外键(、UserID(用户表的外键(和角色 (INT(。Role 列是一个 INT,它的每一个位都应该表示不同的布尔标志(如前面的示例,您可以将其映射到 C# 中的枚举(,并说如果第一个位打开,则用户有权更新描述,如果第二个位打开,用户可以更改计划等等。
[Flags]
enum ProjectAccessRole
{
UpdateDescription,
ChangeSchedule,
etc...
}
在代码中,您可以测试用户的角色是否有权以这种方式更新计划:
if( (intUserRole & ProjectAccessRole.ChangeSchedule)
== ProjectAccessRole.ChangeSchedule)
{
/*user has right*/
}
然后,您可以将此检查包装到一个简单的函数中,该函数采用两个参数,1( 角色,如果它具有 2( 角色,则要检查该角色。然后你只需打电话给HasRights(intUserRole, ProjectAccessRole.ChangeSchedule);
.