ЖАНРЫ

Шрифт:

AuthorizeAttribute — весьма полезный атрибут, который позволяет задавать группы и пользователей, имеющих доступ к заданному действию контроллера или ко всему контроллеру сразу. В нашем примере для проверки прав на доступ к действию контроллера AdminController мы создали следующий метод:

[NonAction]

private bool UserIsAdmin

{

return User.IsInRole("Administrators");

}

С использованием атрибута AuthorizeAttribute нужда в этом методе пропадает. Чтобы продемонстрировать действие AuthorizeAttribute, перепишем контроллер AdminController по-новому,

так, как показано в листинге 4.3.

Листинг 4.3

public class AdminController : Controller

{

[AcceptVerbs(HttpVerbs.Get)]

[Authorize(Roles = "Administrators")]

public ActionResult Index

{

MembershipProvider mp = Membership.Provider;

int userCount;

var users = mp.GetAllUsers(0, Int32.MaxValue, out userCount);

ViewData.Model = users;

return View ;

}

[AcceptVerbs(HttpVerbs.Post)]

[Authorize(Roles = "Administrators")]

public ActionResult Select(Guid? userId)

{

if (!userId.HasValue)

throw new HttpException(404, "Пользователь не найден");

MembershipProvider mp = Membership.Provider;

MembershipUser user = mp.GetUser(userId, false);

ViewData.Model = user;

return View ;

}

[AcceptVerbs(HttpVerbs.Post)]

[Authorize(Roles = "Administrators")]

public ActionResult Update(Guid? userId, string email,

bool isApproved, bool isLockedOut)

{

if (!userId.HasValue)

throw new HttpException(404, "Пользователь не найден");

MembershipProvider mp = Membership.Provider;

MembershipUser user = mp.GetUser(userId, false);

user.Email = email; user.IsApproved = isApproved;

if (user.IsLockedOut && !isLockedOut)

user.UnlockUser;

mp.UpdateUser(user);

return RedirectToAction("Index");

}

[AcceptVerbs(HttpVerbs.Get)]

[Authorize(Roles = "Administrators")]

public ActionResult Delete(Guid? userId)

{

if (!userId.HasValue)

throw new HttpException(404, "Пользователь не найден");

MembershipProvider mp = Membership.Provider;

MembershipUser user = mp.GetUser(userId, false);

mp.DeleteUser(user.UserName, true);

return RedirectToAction("Index");

}

}

Как вы можете заметить, мы избавились от рутинной операции проверки права доступа к действию контроллера путем задания для каждого действия атрибута [Authorize(Roles = "Administrators")]. Этот атрибут предписывает механизму MVC выполнить проверку права доступа пользователя при попытке вызвать действие нашего контроллера. Важным достоинством данного атрибута является его элегантность и унификация. Вместо того чтобы самим писать такой важный код, как код проверки прав доступа, мы оперируем механизмом метаданных в виде атрибута AuthorizeAttribute, помечая нужные нам участки кода. Так снижается возможность ошибки программиста, которая в случае работы с задачей безопасности может стоить очень дорого. Другим плюсом использования атрибута AuthorizeAttribute является заметное уменьшение кода, особенно в сложных вариантах, когда требуется предоставить доступ набору групп и пользователей.

Атрибут AutorizeAttibute принимает два параметра:

? Roles — позволяет задавать перечисление ролей, которые имеют доступ к действию, через запятую;

? Users — позволяет задавать перечисление пользователей,

которые имеют доступ к действию, через запятую.

Так, например, следующий фрагмент кода определяет, что доступ к действию могут получить только члены группы Administrators и пользователи SuperUserl и SuperUser2:

[Authorize(Roles = "Administrators", Users = "SuperUserl, SuperUser2")]

HandleErrorAttibute

Атрибут HandleErrorAttribute предназначен для того, чтобы однообразно сформировать механизм обработки необработанных в контроллерах исключений. Атрибут HandleErrorAttribute применим как к классу контроллера, так и к любому действию. Кроме того, допустимо указывать атрибут несколько раз. По умолчанию, без параметров, механизм MVC с помощью атрибута HandleErrorAttribute при возникновении исключения произведет переадресацию на представление Error, которое должно находиться в папке -/Views/Shared. Однако это действие можно изменить под свои потребности. Для манипулирования порядком действия атрибута HandleErrorAttribute у него есть ряд параметров:

? ExceptionType — указывает тип исключения, на возникновение которого должен реагировать данный атрибут;

? View — указывает представление, которое нужно показать пользователю при срабатывании атрибута;

? Master — указывает наименование Master View, которое будет использоваться при демонстрации пользователю представления;

? Order — указывает на последовательный номер, в порядке которого атрибут будет исполняться.

Для демонстрации работы атрибута HandleErrorAttribute создадим представление AdminError, которое будет использоваться только тогда, когда произойдет ошибка при работе с контроллером AdminController. В листинге 4.3 представлен код представления.

<%@ Page Title="" Language="C#"

MasterPageFile="~/Views/Shared/Site.Master"

Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent"

runat="server">

Ошибка! Произошло необработанное исключение.

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent"

runat="server">

<% var model = (HandleErrorlnfo)ViewData.Model; %>

<h2>Внимание</h2>

<р>При работе сайта произошла исключительная

ситуация в действии <%= model.ActionName %>

контроллера <%= model.ControllerName %>.

Ниже представлена дополнительная информация об исключении:

<%= model.Exception.Message %>

<%= model.Exception.StackTrace %>

</asp:Content>

Обратите внимание, для получения доступа к расширенной информации об исключении мы используем свойство Model объекта ViewData, предварительно приведя его к типу HandleErrorInfo. Механизм атрибута HandleErrorAttribute создает для представления элемент типа HandleErrorInfo, объект которого содержит следующие данные:

? ActionName — имя действия, в котором произошло исключение;

? ControllerName — имя контроллера, в котором произошло исключение;

? Exception - объект типа Exception, в котором содержится вся информация об исключении, в том числе строка сообщения и трассировка стека.

Для того чтобы проверить наше представление, создадим для тестирования новое действие TestException в контроллере AdminController:

public ActionResult TestException

Поделиться с друзьями: