MVC视图中的安全性

时间:2011-10-20 17:51:56

标签: c# asp.net-mvc razor

在我的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")
}

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

4 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:3)

我之前完成此操作的一种方法是创建一个继承自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");
        }

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

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

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

所以准备ViewModel应该有它应该拥有的数据,让View只渲染它。 (你正在使用它的布尔属性就足够了)