问题 MVC视图中的安全性


在我的MVC应用程序中,我有几个不同的角色:管理员,普通用户等等。

我知道我可以通过Authorize属性将安全性应用于我的控制器:

[Authorize(Roles="Admin")]
public ActionResult Create()
{
    return View();
}

但是我还需要对视图应用一些安全性,以便不向某些角色显示View的某些部分:

@if( User.IsInRole("Admin") )
{
    @Html.ActionLink("Create", "Create")
}

以上述方式执行此操作会更好,还是在ViewModel中处理此类安全性:

public ActionResult Index()
{
    var model = new IndexViewModel();

    model.CanCreate = User.IsInRole("Admin");

    return View(model);
}

View:
@( Model.CanCreate )
{
    @Html.ActionLink("Create", "Create")
}

第二种方法与第一种方法相比是否有任何好处,还是仅仅是一种偏好?


5554
2017-10-20 17:51


起源

我认为第一种方法更好。 - Birey


答案:


第二种方式更受欢迎,因为您的业务逻辑将保持在模型级别。

在您的示例中,业务逻辑非常简单。但是,假设需求已经发生变化,现在不仅管理员可以创建内容,而且还可以创建超过1个月前注册的普通用户。有了业务逻辑,您必须更新所有视图。


6
2017-10-20 17:58





我之前完成此操作的一种方法是创建一个继承AuthorizeAttribute的动作过滤器。可以像DisplayIfAuthorizedAttribute一样调用过滤器,除了标准的AuthorizeAttribute属性之外,还有一个名为ViewNameIfNotAuthorized的属性。

该属性调用base方法进行授权,如果失败,则返回ViewNameIfNotAuthorized视图。否则,它允许action方法正常进行。

然后,您将通过操作方法呈现这些部分视图,并通过父视图中的Html.RenderAction或Html.Action调用操作方法。这些操作方法将使用属性进行修饰。

您现在有一种标准化的方法来执行此操作,并且没有授权代码污染您的操作方法的内部。

这就是过滤器的样子:

public class DisplayIfAuthorizedAttribute : System.Web.Mvc.AuthorizeAttribute
{
    private string _ViewNameIfNotAuthorized;
    public DisplayIfAuthorizedAttribute(string viewNameIfNotAuthorized = null)
    {
        _ViewNameIfNotAuthorized = viewNameIfNotAuthorized;
    }
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        bool isAuthorized = base.AuthorizeCore(filterContext.HttpContext);

        if (!isAuthorized)
        {
            filterContext.Result = GetFailedResult();
        }
    }

    private ActionResult GetFailedResult()
    {
        if (!String.IsNullOrEmpty(_ViewNameIfNotAuthorized))
        {
            return new ViewResult { ViewName = _ViewNameIfNotAuthorized };
        }
        else
            return new EmptyResult();
    }
}

您的操作方法将装饰为:

[DisplayIfAuthorized("EmptyView", Roles="Admin")]
        public ViewResult CreateLink()
        {
            return View("CreateLink");
        }

3
2018-02-07 18:11





你可能需要两个......

请注意,仅第二个不安全,用户可能能够在浏览器地址栏中构建actionlink的URL。所以你绝对需要安全属性。

第二个更多的是用户友好性或UI设计。也许您希望用户能够单击“创建”,然后可以选择以不同方式登录。


1
2017-10-20 17:56



我并不是说我不会对行动进行[授权]。问题是我应该通过在模型中包含属性或直接在我的视图中调用User.IsInRole()来处理我的View安全性。 - Dismissile


检查控制器中的授权,并根据角色的规则为视图准备Viewmodel。

视图用于简单地显示数据。所以,imo,他们不必做角色检查等。

因此,请准备ViewModel及其应具有的数据,并让View仅渲染它。 (您使用它的布尔属性足够imo)


0
2017-10-20 18:00