Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 在MVC(ASP)中对同一数据实现多个角色_Asp.net_Asp.net Mvc - Fatal编程技术网

Asp.net 在MVC(ASP)中对同一数据实现多个角色

Asp.net 在MVC(ASP)中对同一数据实现多个角色,asp.net,asp.net-mvc,Asp.net,Asp.net Mvc,例如: 我们有两种用户类型 供应商用户 工厂用户 它们都与基本相同的数据交互,但一般来说,Factory用户可以编辑比供应商用户多得多的信息 使用ASP.NET4.5,我将使用MVC实现所有这些 一些总结用例:(假设已登录) FactoryUser: 可编辑消息页面,显示供应商的最新公告 订单确认页面和订单查看页面 供应商编辑页面(用于更新多个供应商的地址等) 供应商用户: -可以查看来自特定工厂的消息。 -可以创建订单、发送和查看。 -可以编辑自己的信息 正如您所看到的,这只是大量使用

例如:

我们有两种用户类型

  • 供应商用户
  • 工厂用户
它们都与基本相同的数据交互,但一般来说,Factory用户可以编辑比供应商用户多得多的信息

使用ASP.NET4.5,我将使用MVC实现所有这些

一些总结用例:(假设已登录)

FactoryUser:

  • 可编辑消息页面,显示供应商的最新公告
  • 订单确认页面和订单查看页面
  • 供应商编辑页面(用于更新多个供应商的地址等)
供应商用户: -可以查看来自特定工厂的消息。 -可以创建订单、发送和查看。 -可以编辑自己的信息

正如您所看到的,这只是大量使用各种权限编辑信息。我的问题是,我应该从哪里开始分居

关于:

  • 模型-我认为这一个与数据库保持一致
  • ViewModels-我是否为每个角色编写不同的视图?如果是,2个文件/类
  • 控制器-相同,我是否编写不同的函数??上课?如果是这样,那么拥有[授权角色]的意义是什么,只是为了防止未经授权的访问&而不是为了分割
  • 视图-我是否尝试对大多数零件使用相同的视图,并以某种方式包含关于它们是否具有“编辑”按钮的逻辑
  • 局部视图-它们是否可用于视图上可能存在或不存在的“编辑”按钮
  • 查看布局-
  • 过滤器-我可以做一些奇特的逻辑,将所有内容放在完全不同的2个文件夹(整个MVC)中,然后在路由/授权级别将其拆分
  • 路由-
  • 在上面的每一个例子中,我都可以看到根据用户类型划分逻辑的可能性。当然,我想用最简单、最理智的方式来做这件事

    是否有某个地方的文件规定了应该如何做到这一点,或者是否有任何明智的人曾经这样做过,并遇到了所有的问题

    谢谢
    (第一个问题!)

    一种方法是创建功能。e、 g
    查看订单、创建订单、更新订单、删除订单

    这些
    功能
    随后将分配给
    角色
    ——并且该角色可以分配给
    用户

    因此,DB将如下所示:

    现在,当用户登录时,您将读取分配给用户的所有功能,并将它们保存在会话中(创建SessionHandler类)

    UserDTO类的示例

    public class UserDTO
    {
         public int UserId {get;set;}
         public List<string> Features {get;set;}
    }
    
    因此,在控制器中调用
    Login
    函数,并在
    SessionHandler

    public class SessionHandler
    {
        private const string SessionKey = "UserSession";
    
        public static UserDTO UserSession
        {
            get
            {
                return HttpContext.Current.Session[SessionKey] != null
                           ? (UserDTO)HttpContext.Current.Session[SessionKey]
                           : null;
            }
            set { HttpContext.Current.Session[SessionKey] = value; }
        }
    }
    
    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
       var user = Login(model.username, model.password);
    
       if(user == null) return View(model);
    
       SessionHandler.UserSession = user;
    
       // TODO: redirect to Home Page - after login
    
        return RedirectToAction("Index", "Home");
    }
    
    然后,您可以在视图中检查用户是否可以执行特定操作,例如,如果您在“查看订单”页面上,如果用户没有权限,您可以隐藏“创建订单”按钮:

        @model WhateverDTO
    
        // Check if user has Create Order Feature in Role 
    
        @if (SessionHandler.UserSession.Features.Contains("Create Order"))
        {
    // Yes, User has permission - then Render the Button
    
         <button> Create Order </button>
    
        }
    
    然后装饰你的行为

    [CustomAuthorize(Roles = "Create Order")]
    // Pass feature name for Roles - if user doesn't have permission to Create Order - the "You do not have permission to perform this action." exception will get thrown
    public ActionResult CreateOrder()
    {
      return View(new CreateOrderDTO());
    }
    
    [HttpPost]
    [CustomAuthorize(Roles = "Create Order")]
    // Pass feature name for Roles - if user doesn't have permission to Create Order - the "You do not have permission to perform this action." exception will get thrown
    public ActionResult CreateOrder(CreateOrderDTO model)
    {
    
      return View(model);
    }
    
    上述方法的优点是,您可以根据需要添加任意多的用户角色,而无需更改代码


    模型-我认为此模型与数据库保持一致

    模型是相同的-相同的DB相同的模型

    视图模型-我是否为每个角色编写不同的视图?如果是,则为2个文件/类?

    不,不要使事情复杂化-使用相同的ViewModel/DTO

    控制器-相同,我是否编写不同的函数??上课?如果是这样的话,那么拥有[授权角色]只是为了防止未经授权的访问,而不是为了分裂,这有什么意义呢?

    不需要单独的操作/视图或控制器

    视图-我是否尝试对大多数零件使用相同的视图,并以某种方式包含关于它们是否有“编辑”按钮的逻辑?

    是,使用相同的视图-根据用户角色/功能隐藏/显示操作

    局部视图-它们是否可用于视图上的“编辑”按钮?

    按钮不需要局部视图

    查看布局-? 过滤器-我可以做一些奇特的逻辑,将所有内容放在完全不同的2个文件夹(整个MVC)中,然后在路由/授权级别将其拆分 路由-?


    {Authorize]只允许或不允许访问操作/控制器。您可以检查视图中的用户角色,并根据角色隐藏或显示不同的操作,您能告诉我这些文件理想的放置位置吗?(MVC结构)我已经实现了这一点,它可以工作了,谢谢:)让我知道我应该在哪里放置与命名空间/文件夹相关的类/file@Worthy7这完全取决于应用程序的体系结构-SessionHandler应该添加到MVC Web应用程序的子文件夹中,例如Helpers。如果您有单独的DTOs枚举,然后将它们放在那里-否则将它们添加到MVC Web项目的子文件夹中。
    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
    
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException("httpContext");
            if (httpContext.Session == null)
                return false;
    
            // Checking Authenticaiton
            var userSettings = SessionHandler.UserSession;
            if (userSettings == null)
                return true;
    
            //Checking Authorization
            if (Roles.Length == 0)
                return true;
    
    
            var actionFeatures = Roles.Split(',');
            if (!actionFeatures.Any(s => userSettings.Features.Contains(s)))
                throw new UnauthorizedAccessException("You do not have permission to perform this action.");
            return true;
        }
    }
    
    [CustomAuthorize(Roles = "Create Order")]
    // Pass feature name for Roles - if user doesn't have permission to Create Order - the "You do not have permission to perform this action." exception will get thrown
    public ActionResult CreateOrder()
    {
      return View(new CreateOrderDTO());
    }
    
    [HttpPost]
    [CustomAuthorize(Roles = "Create Order")]
    // Pass feature name for Roles - if user doesn't have permission to Create Order - the "You do not have permission to perform this action." exception will get thrown
    public ActionResult CreateOrder(CreateOrderDTO model)
    {
    
      return View(model);
    }