Безопасность в MVC Views - PullRequest
       4

Безопасность в MVC Views

11 голосов
/ 20 октября 2011

В моем приложении MVC у меня есть несколько разных ролей: Администратор, Обычный пользователь и т. Д. И т. Д.

Я знаю, что могу применить безопасность к своим контроллерам через атрибут Authorize:

[Authorize(Roles="Admin")]
public ActionResult Create()
{
    return 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 ]

6 голосов
/ 20 октября 2011

Второй способ более предпочтителен, поскольку ваша бизнес-логика останется на уровне модели.

В вашем примере бизнес-логика очень проста. Однако представьте, что требования изменились, и теперь контент могут создавать не только администраторы, но и обычные пользователи, которые зарегистрировались более 1 месяца назад. С учетом бизнес-логики вам придется обновить все ваши представления.

3 голосов
/ 07 февраля 2012

Один из способов, которые я делал ранее, - это создание фильтра действий, который наследуется от атрибута AuthorizeAttribute.Фильтр может называться как-то типа DisplayIfAuthorizedAttribute, и в дополнение к стандартным свойствам AuthorizeAttribute имеет свойство ViewNameIfNotAuthorized.

Атрибут вызывает базовый метод для авторизации, а в случае сбоя возвращает представление ViewNameIfNotAuthorized.В противном случае, он позволяет методу действия действовать нормально.

Затем вы должны визуализировать эти частичные представления с помощью методов действия и вызывать методы действия с помощью 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");
        }
1 голос
/ 20 октября 2011

Вам могут понадобиться оба ...

Обратите внимание, что один второй не будет безопасным, пользователь может создать URL-адрес для ссылки на действие в адресной строке браузера. Так что вам абсолютно необходим атрибут безопасности.

Второй вопрос больше связан с удобством использования или дизайном пользовательского интерфейса. Возможно, вы хотите, чтобы пользователь мог щелкнуть «Создать», а затем выбрать другой вариант входа в систему.

0 голосов
/ 20 октября 2011

Проверьте авторизацию в вашем контроллере и подготовьте Viewmodel для представления в соответствии с правилами вашей роли.

Представления используются для простого отображения данных.Поэтому, имхо, им не нужно проверять роли и т. Д.

Так что подготовьте ViewModel с данными, которые он должен иметь, и пусть View только визуализирует его.(логическое свойство, которое вы используете, достаточно imo)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...