【问题标题】:Role Management in MVC3MVC3 中的角色管理
【发布时间】:2011-09-09 23:20:36
【问题描述】:

我想向应用程序添加一个功能,这样只有管理员才能创建用户,并且他可以向用户提供对特定页面的访问权限。

他可以创建角色,可以为用户提供不同的角色。

我正在使用 Visual Studio 2010 并在 MVC3 中构建此应用程序。

请给我一些建议。

提前致谢。

【问题讨论】:

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


    【解决方案1】:

    检查MvcMembership,也可以在Nuget 上找到。您将掌握 ASP.NET MVC 3 站点中用户管理的所有基础知识。

    您将需要一个用户/角色提供者。阅读this tutorial 以了解如何设置将保存您的用户和角色的数据库。设置完成后,您将创建首次设置/手动测试所需的所有存储过程。

    【讨论】:

      【解决方案2】:

      1.使用 Authorize 属性装饰您的用户创建和权限设置操作 (请注意,使用 AuthorizeAttribute 的 Roles 属性需要实现 MembershipProvider(标准或自定义)并在 web.config 中注册)

      public class AccountController : Controller
      {
      [HttpGet, Authorize(Roles = "Admin")]
      public ViewResult CreateUser()
      {
          return View();
      }
      
      [HttpPost, Authorize(Roles = "Admin")]
      public ActionResult CreateUser()
      {
          //... call service method to create user
      }
      
      [HttpPost, Authorize(Roles = "Admin")]
      public ActionResult AssignPageToUser(int userId, string controllerName, string ActionName)
      {
          //... insert record into table (UserPermissions) with attributes (userId, actionName, controllerName)
          }
      // other methods without decoration by authorize attribute
      }
      

      如果您真的想分别完全控制每个用户的操作权限,那么接下来的段落是正确的。 如果您认为,您的权限可以在角色上进行有限和少量分组 - 您可以通过授权属性装饰所有操作/控制器并指定角色,其中操作/控制器可用:[Authorize("Customer, Manager, RegionalAdmin")] 并让管理员可以将角色分配给用户.但是请记住,仅在列出的角色中的 1 个角色中就足以获得访问权限,您不能通过此属性要求,例如管理员和经理角色。 如果您想要求一定超过 1 个角色,请使用多个属性:

      public class MyController:Controller
      {
      [Authorize(Roles = "Manager")]
      [Authorize(Roles = "Admin")]
      public ActionResult Action1()
      {
      //...
      }
      }
      

      2.对于您的页面,您可以创建自己的过滤器属性,从授权属性继承,这将检查用户是否可以使用操作(我认为您想要分配操作而不是视图给用户)。

      public UserPermissionRequiredAttribute: AuthorizeAttribute
      {
      public OnAuthorization(AuthorizationContext filterContext)
      {
      var isAuthenticated = filterContext.HttpContext.User.Identity.IsAuthenticated;
      var userName = filterContext.HttpContext.User.Identity.Name;
      var actionName = filterContext.ActionDescriptior.ActionName;
      var controllerName = filterContext.ActionDescriptior.ControllerDescriptor.ControllerName;
          if (isAuthenticated && myUserActionPermissionsService.UserCanAccessAction(userName, actionName, contollerName)
      {
      filterContext.Result = HttpUnauthorizedResult(); // aborts action executing
      }
      }
      }
      

      3.装饰操作(控制器),管理员授权的用户可以访问:

      MySpecialController: Controller
      {
      [UserPermissionRequired]
      Action1()
      {
      //...
      }
      
      [UserPermissionRequired]
      Action2()
      {
      //...
      }
      
      Action3()
      {
      //...
      }
      

      }

      我不建议为此目的使用基本控制器,因为属性使用更灵活(您可以控制动作/控制器级别而不仅仅是控制器级别),这是实现职责分离的更好方法。基本控制器和过滤器属性的使用与多态性和切换运算符相关。

      【讨论】:

        【解决方案3】:

        阅读简单的旧表单身份验证,以添加对角色和用户管理的支持。

        然后在控制器或操作上使用[Authorize(Roles="RoleName1")] 来控制访问。

        【讨论】:

          【解决方案4】:

          您提出的问题非常广泛,需要一些时间来审核您的所有要求。在任何情况下,您都可以从向所有其他控制器继承的控制器添加用户属性开始。然后,您可以询问该用户实例以确定他们是否有权访问当前路由。该解决方案应该为您提供添加一些管理视图以满足您的业务需求所需的基础。

          public class MegaController
          {
              protected User CurrentUser { get; set; }
          
              protected override void Initialize(RequestContext context)
              {
                  if (requestContext.HttpContext.User.Identity.IsAuthenticated)
                  {
                      var userRepository = new UserRepository();
                      CurrentUser = userRepository.GetUser(
                          requestContext.HttpContext.User.Identity.Name);
                  }
              }
          }
          

          UserUserRepository 类型可以是您自己设计的。您可以使用 LINQ To Entities 包装一个名为“User”的表,然后在您的控制器中,您可以访问该表中的任何字段。

          然后,从MegaController子类化所有控制器

          public class AdminController : MegaController
          {
              public ActionResult Action1()
              {
                  return View();
              }
          }
          
          public class SomeOtherController : MegaController
          {
              public ActionResult Action1()
              {
                  return View();
              }
          }
          

          现在,这并不能完全解决您的“管理员”问题。为此,您可以在MegaController.Initialize() 中包含逻辑以询问请求信息。一旦你在上下文中获得了请求的路由和用户,你的代码就可以决定是否允许请求、重定向它等等。

          protected override void Initialize(RequestContext context)
          {
              // ...
              if(context.HttpContext != null)
              {
                  if(context.HttpContext.Request.Path == "some/restricted/route" 
                      && CurrentUser.Role != "Admin")
                  {
                      // or similar error page
                      var url = Url.Action("UnAuthorized", "Error");
                      context.HttpContext.Response.Redirect(url);
                  }
              }
          }
          

          使用此方法的一个警告是,添加到您的应用程序的任何新控制器都必须从 MegaController 继承,该架构的未来开发人员很容易错过该项目。

          【讨论】:

          • 有没有可以指导我的教程。
          • @kapil 如果没有其他要求,我无法尝试推荐任何文档。你能在你的原帖中详细说明吗?
          猜你喜欢
          • 1970-01-01
          • 2015-01-02
          • 2016-09-07
          • 1970-01-01
          • 1970-01-01
          • 2012-02-17
          • 1970-01-01
          • 1970-01-01
          • 2016-09-30
          相关资源
          最近更新 更多