Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.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.net_Asp.net Mvc_Asp.net Mvc 4_Asp.net Mvc 5_Entitlements - Fatal编程技术网

如何在asp.net-mvc控制器中集中授权逻辑?

如何在asp.net-mvc控制器中集中授权逻辑?,asp.net,asp.net-mvc,asp.net-mvc-4,asp.net-mvc-5,entitlements,Asp.net,Asp.net Mvc,Asp.net Mvc 4,Asp.net Mvc 5,Entitlements,我有一个ASP.NET-MVC网站,带有SQL Server后端。我有许多控制器操作需要我进行权利检查 现在,我这样做: public ActionResult SomeEntitledPage() { if (_myModel.IsMySiteAdminRole) { return View(new MyViewModel()); } else { r

我有一个ASP.NET-MVC网站,带有SQL Server后端。我有许多控制器操作需要我进行权利检查

现在,我这样做:

    public ActionResult SomeEntitledPage()
    {
        if (_myModel.IsMySiteAdminRole)
        {
            return View(new MyViewModel());
        }
        else
        {
            return View("NotEntitled", new NotEntitledViewModel(){Page = "[PageName]", SupportDG = "support@support.com"});
        }
    }
这很好,但感觉就像我在很多地方复制了这个逻辑

基于以下内容,使多个授权控制器操作“安全”的最佳方式(属性等)是什么

(安全性在于它检查
IsMystiteAdminRole
,如果未授予权限,则返回“未授予权限”视图


我还想确保我没有在每个页面上都有性能损失?

实现这一点的最佳方法是使用属性并用它装饰操作

看看

您可以继承它并执行自己的自定义逻辑。以下是我刚才做的一个项目的示例:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    public bool AdminRequired;
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (UserSession.IsLoggedIn)
            return (!AdminRequired || (AdminRequired && UserSession.IsAdmin));
        else
            return false;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result = new RedirectToRouteResult(
                                   new RouteValueDictionary 
                                   {
                                       { "action", "LogIn" },
                                       { "controller", "Account" },
                                       { "returnUrl", filterContext.HttpContext.Request.RawUrl}
                                   });
    }
}
使用此属性,您可以拥有两个级别的授权:普通用户和管理员用户。示例:

[Authorize(AdminRequired = true)]
public ActionResult AdminOnlyAction()
{
    // perform authorized admin tasks
}

[Authorize]
public ActionResult RegularUserAction()
{
    // perform authorized regular user action
}

我更喜欢对权限/特权逻辑使用操作过滤器。这些过滤器的优点是,它们可以在操作方法填充模型后运行

例如:

public class AdminOnlyFilterAttribute : ActionFilterAttribute
{
      public override void OnActionExecuted(ActionExecutedContext filterContext)
      {
        if (!filterContext.Controller.ViewData.Model.IsMySiteAdminRole)
            {
                filterContext.Result = new ViewResult
                {
                    ViewName = "NotEntitled",
                    Model = new NotEntitledViewModel(){Page = "[PageName]", SupportDG = "support@support.com"}
                };
            }
        base.OnActionExecuted(filterContext);
    }   
}
动作过滤器允许您有选择地覆盖控制器的
OnActionExecuted
方法


此属性可以应用于特定操作或整个控制器。结果将取决于您的模型值,并且只会更改您的视图。

我同意这里的其他人的看法,即您可以使用属性来完成此操作,但我只想指出另一种替代方法。您可以编写一个基本控制器,所有c需要权限检查的控制器继承。在该控制器中,您可以编写逻辑来检查权限:

public class BaseController : Controller
{
    private readonly bool _isEntitled;

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);
        // Your logic for entitlement check goes here.
        // Set _isEntitled to true if user is entitled to view page.
    }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!_isEntitled) {
           // Redirect user which is not entitled.
           filterContext.Result = new ViewResult
                                  {
                                     ViewName = "NotEntitled",
                                     Model = new NotEntitledViewModel(){Page = "[PageName]", SupportDG = "support@support.com"}
                                  };
        }
    }
}
现在,您所要做的就是在需要进行授权检查的所有控制器中继承此控制器:

  public MyController : BaseController
  {
      // Action in here...
  }
我并不是说这是一个更好的选择,我只是指出了一种做你需要的事情的替代方法。此外,如果你想确保权限检查不会在每个页面请求上发生,而只在用户登录时发生一次…

TL;DR: 查看扩展您的用户配置文件,并在用户通过身份验证时用角色信息填充它


在我看来,问题似乎源于安全层的设计,因为您正在检查的用户只在错误的执行阶段可用,这导致了这种复杂性。看起来您试图做的是检查发出请求的用户,看看他是否满足特定的角色要求,并向他们显示一个u未经授权的页面,如果它们不符合要求(漂亮的教科书内容),但由于某些原因,该用户位于视图模型中,并且该视图模型在控制器完全实例化之前不会生成,这意味着您无法检查它是否在管道中初始化。草率的解决方案是覆盖控制器上的initialize方法,调用base方法,但在基本初始化为c之后执行一些工作完成。那么你的数据应该准备好了。但那太草率了


一般来说,您的会话用户应该以UserProfile或扩展标识的形式出现在会话中。通过这样做,您可以填充该用户的角色以及其他角色,然后在控制器/操作执行管道的任何阶段对其进行检查;然后您可以使用自定义属性检查user.IsInRole(“任意”)。您不需要该操作来返回“未授权”视图,因为您可以在“授权”属性HandlUnauthorizedRequest override的响应中设置该视图。

我同意其他人建议的解决方案

您提到的是,您需要在需要检查模型IsInAdminRole属性的任何位置复制代码。因此,我创建了一个通用方法,用于传递模型和viewname/path。在ISENTITED方法中,只需检查isadminrole属性并采取必要的措施

注意:这只是一个简单的示例解决方案。您可以检查这是否有帮助或提供一些提示

做如下事情

样本模型

public class NoRights
{
    public string Message { get; set; }
}

public class MyModel
{
    public bool IsAdminRole { get; set; }
}
这是家庭控制器

public class HomeController : Controller
{

    public ActionResult Index()
    {
        var mod = new MyModel() { IsAdminRole = true };
        return IsEntitled(mod, "IndeX");
        //return View();
    }
}
这是一个示例静态方法,可以放在helper类中。 注意:这将返回一个标准错误视图,其中包含在
NoRights
模型的message属性中指定的错误消息

    public static ViewResult IsEntitled(object model, string viewPath)
    {
        var prop = model.GetType().GetProperty("IsAdminRole");
        var hasRights = (bool)prop.GetValue(model, null);
        var viewResult = new ViewResult();
        if (hasRights)
        {
            viewResult.ViewData = new ViewDataDictionary(model);
            viewResult.ViewName = viewPath;
        }
        else
        {
            viewResult.ViewData = new ViewDataDictionary(
                new NoRights() { Message = "Your dont have rights" });
            viewResult.ViewName = "Error";

        }
        return viewResult;
    }
如果我在
IsAdminRole
属性中传递true,这里就是输出

如果我在
IsAdminRole
属性中传递false,我将得到以下输出


希望这能有所帮助。

我们有一个类似的案例,要求将授权逻辑完全设置在一个集中的位置。为此,您可以尝试类似的方法

首先,您可以有一个应用程序级控制器,它可以

public class ApplicationController : Controller
{
    protected override void OnActionExecuted(ActionExecutedContext ctx)
    {
        base.OnActionExecuted(ctx);

        if (!_myModel.IsMySiteAdminRole)
        {
            ctx.Result = View("NotEntitled", new NotEntitledViewModel(){Page = "[PageName]", SupportDG = "support@support.com"});
        }
    }
}
现在此控制器可以在其他控制器中继承。您的整个授权逻辑现在集中在一个控制器中

public class EntitlementController: ApplicationController
{
    return View(new MyViewModel());
}

我只需要在一个特定的控制器中执行此操作(它有一个对“model”类的引用,该类可以告诉我用户是否有权使用该函数。我如何将其注入到该控制器中,以便调用“\u myModel.ismysteadminrole”在AuthorizeCore方法中?我不认为放置在控制器操作上的属性可以感知该操作的控制器。您可以尝试“搜索”对于传递的
httpContext
。我的建议是将
\u myModel.ismysteadminrole
提取到一个类中,该类知道可以从属性访问的
httpContext
。在我的示例中,
UserSession
是一个静态类,其属性使用
httpContext.Current.Session
存储va当前用户的lues。我不希望每个控制器中的每个操作都被授予权限。这只是一些控制器中的一些操作。您的答案如何满足