【问题标题】:need some idea about how to manage roles in my application (ASP.NET MVC3)需要一些关于如何在我的应用程序中管理角色的想法(ASP.NET MVC3)
【发布时间】:2012-05-15 10:00:09
【问题描述】:

我正在开发一些网站,它是一种在线工作场所,会有一些用户和一些正在进行的计算机编程项目,每个用户可以有多个角色,例如一个特定用户可以是一个项目的项目经理和另一个项目的开发人员。自然,项目经理在项目中比开发者拥有更多的权力。我的问题是如何在我的代码中巧妙地管理这个?我打算使用我的自定义角色提供程序并使用 Authorize 属性,但这还不够,因为我需要项目 ID 加上用户 ID 才能在特定项目中查找用户的角色。

【问题讨论】:

  • 如何向 aspnetdb 数据库添加两列(或使用表进行规范化)。将项目 ID 广告到连接到用户的 project_manager 表和 developer_table 并检查这些。我在一个项目中使用了类似的解决方案,它就像一个魅力:)
  • 每个项目只有1个项目经理吗?如果是这种情况,我会将项目经理的用户 ID 存储在项目表中。每次查询项目(显示)时,您都可以检查访问它的用户是否是 PM。
  • @Luke,不,不应该有任何限制
  • @Magnus,我宁愿不使用任何数据库解决方案,我想开发一个灵活的代码

标签: c# asp.net asp.net-mvc-3 roles roleprovider


【解决方案1】:

首先,您必须为您的扩展角色管理创建额外的表,例如projects,并在operations 的上下文中与users 建立关系,这可能是您的controller's actions

一种方法是为roles 创建自己的表。在这种情况下,您将只使用 Asp net 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 方法中,您可以获得自定义授权逻辑中可能需要的所有信息,例如HttpContextController 名称、Action 名称。您只需从此方法调用您的自定义身份验证逻辑。 您的自定义身份验证逻辑可能如下所示。

 public class CustomAuthenticationLogic
{
    public static bool IsAccessAllowed(string controller, string action, IPrincipal user, string ip)
    {
        //
        // Your custom logic here              
        //              
    }
} 

【讨论】:

  • 我们应该把这个“OnAuthorization”代码放在哪里?以及它如何与所有操作联系起来。它是否通过属性链接 - [CustomAuthorize]。?这个“CustomAuthorize”是我的类名,它继承自 -“System.Web.Http.Filters.FilterAttribute”,并且我有“OnAuthorization”代码或方法。但仍然授权不起作用。断点未命中“OnAuthorization”代码。
  • @pvaju896 是;您需要在操作上添加 customAuthorizeAttribute 才能调用 OnAuthorization 方法 // 为此,您必须从 FilterAttribute 中继承您的类,并且还必须实现 IAuthorizationFilter 接口。 //
  • 我在控制器中的操作;公共类 PersonController : Controller { [SmartClinic.Util.CustomAuthorize] [HttpGet] public ActionResult List() {
  • 还有一个带有 onAuthorization 代码的类: public class CustomAuthorize : System.Web.Http.Filters.FilterAttribute, System.Web.Http.Filters.IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) {
  • 和你上次提到的另一门课;自定义身份验证逻辑
【解决方案2】:

我不久前做了一些研究,可以向您保证:

  1. ASP.NET 内置功能很可能无济于事(无法考虑项目 ID 之类的内容)
  2. 基于角色的访问模型是最合适的,有不同的实现方式。 Rusted 建议的 AzMan 实际上很好,但是管理上下文相关的规则可能会很困难。例如:用户 A 在项目 C 中执行操作 B,而它可以说是星期天。看看 azman。
  3. 将访问规则与代码混用是非常糟糕的。您的安全模型不需要与应用程序的工作方式相关(ASP.NET MVC) 所以这个是错误的:
var isAllowed = AccessControl.IsAccessAllowed(controller, action, user, ip);

它必须看起来像:

var isAllowed = AccessControl.IsAccessAllowed(user, operation, context);

然后你可以在任何时候使用它,在每个动作中或将它包装为属性。

其中操作是“登录”、“发布回复”、“阅读主题”等。上下文是其他所有内容,例如“项目 id”、“星期几”、“用户 ip”等

可以写很多东西,比如角色重叠、上下文等。 简而言之:Google 的“.NET 基于角色的访问模型”可能更容易编写小型自定义安全框架。使其与用户、角色、操作和项目 ID 一起使用

操作被分配给角色, 角色分配给具有定义项目 ID 的用户, 您可以对操作和角色进行硬编码,因此在您的数据库中只有一个小变化:用户到角色的映射

【讨论】:

  • 仅供参考 - 企业库中有很多优秀的库可用于处理 Azman 和 ADLDS
【解决方案3】:

如果您有更复杂的规则并且属性不够,那么您可以在 Controller 中计算用户是否可以访问某些功能并在您的 ViewModel 中添加反映访问或不访问这些功能的属性。

这样您的视图会非常纤细,它会根据那些 ViewModel 布尔属性显示内容。

因此,假设您的用户只能阅读,您可以拥有一个属性 bool IsReadOnly,它会根据授权规则填充到控制器中,并且可以在视图中使用,例如,生成标签而不是文本框。

【讨论】:

    【解决方案4】:

    我喜欢AzMan 的主要思想是针对操作进行编程的概念。

    Operations 是非常精细的东西,在使用上应该没有重叠,并且只能由开发人员定义。 通过将操作分组到任务中,将任务分组到角色中,然后将主体(用户和组)映射到角色,您拥有一个非常强大的模型来在您的应用程序中定义授权。由于您直接对操作进行编程,因此您的代码不需要知道用户具有哪些角色,并且管理员可以在运行时更改这些角色。事实上,有人可以定义一组完全不同的角色来使用您在代码中使用的操作,而您根本不需要更改任何代码。这才是真正的力量所在。

    我的意思不是“在您的应用程序中使用 AzMan”(但也许您应该尝试一下)。这是一个强大的模型,但它也很复杂,对于简单的事情可能有点过分了。如果您只有一个或两个角色,并且他们保护的操作不重叠或不太可能改变,那么它 可能没有保证。

    【讨论】:

      【解决方案5】:

      我建议您通过扩展内置的AuthorizeAttribute 过滤器而不是实现IAuthorizationFilter 接口来创建自定义Authorize 过滤器。内置的AuthorizeAttribute 做了许多处理缓存问题和其他事情的管道工作,如果你要实现接口,你必须完成所有这些工作。

      您必须重写 AuthorizeCore 方法,然后您就可以完成所有角色检查逻辑。 user id 你必须存储在会话中,project id 你必须弄清楚。

      public override bool AuthorizeCore(HttpContextBase httpContext)
      {
      
      }
      

      AuthorizeAttribute 源代码 - 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

      【讨论】:

        【解决方案6】:

        您可以基于roles 拥有groups

        然后将不同的用户添加到特定的组。组可以是 >

        1) Admin Group  
        2) Developer Group  
        3) Project1-QA Group  
        4) Project2-Manager Group
        

        保存[user - group][group - projects] 的映射,具体取决于您的数据库设计。

        您可以为一个用户拥有任意数量的角色(组)。

        【讨论】:

          【解决方案7】:

          一种非常简单的方法 - 对于站点范围的访问控制,您可以将一个 INT 列添加到用户表并将该 INT 的每一位映射到一个 [flags] 枚举 - 例如[Flags] enum Access { UpdateProjects, AddProjects }.

          对于每个项目的访问控制,创建一个名为 e.g. ProjectAccessControl 包含三列:ProjectID(Project 表的外键)、UserID(User 表的外键)和 Role (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);

          【讨论】:

            猜你喜欢
            • 2013-10-16
            • 1970-01-01
            • 1970-01-01
            • 2015-02-02
            • 2011-09-09
            • 2020-12-11
            • 1970-01-01
            • 2012-06-29
            • 1970-01-01
            相关资源
            最近更新 更多