ASP.NET MVC удобная ошибка 401
Я реализовал обработку ошибок на сайте ASP.NET MVC так, как предлагает этот пост.
С 404 ошибками все работает нормально. Но как правильно показать удобный экран для ошибки 401? Они обычно не выдают исключение, которое может быть обработано внутри Application_Error()
а скорее действие возвращает HttpUnauthorizedResult. Один из возможных способов - добавить следующий код в конец Application_EndRequest()
метод
if (Context.Response.StatusCode == 401)
{
throw new HttpException(401, "You are not authorised");
// or UserFriendlyErrorRedirect(new HttpException(401, "You are not authorised")), witout exception
}
Но внутри Application_EndRequest()
Context.Session == null, errorController.Execute()
терпит неудачу, потому что он не может использовать TempDataProvider по умолчанию.
// Call target Controller and pass the routeData.
IController errorController = new ErrorController();
errorController.Execute(new RequestContext(
new HttpContextWrapper(Context), routeData)); // Additional information: The SessionStateTempDataProvider requires SessionState to be enabled.
Итак, можете ли вы предложить несколько лучших советов о том, как "удобно обрабатывать" 401 в приложении ASP.NET MVC?
Благодарю.
4 ответа
Посмотрите на атрибут HandleErrorAttribute. Подкласс от него или добавить свою собственную реализацию, которая будет обрабатывать все коды состояния, которые вас интересуют. Вы можете сделать так, чтобы он возвращал отдельное представление об ошибке для каждого типа ошибки.
Вот идея, как создать фильтр исключений ошибок дескриптора. Я выбросил большинство вещей, чтобы сосредоточиться только на наших основах. Абсолютно взгляните на оригинальную реализацию, чтобы добавить проверки аргументов и другие важные вещи.
public class HandleManyErrorsAttribute : FilterAttribute, IExceptionFilter
{
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
return;
Exception exception = filterContext.Exception;
string viewName = string.Empty;
object viewModel = null;
int httpCode = new HttpException(null, exception).GetHttpCode();
if (httpCode == 500)
{
viewName = "Error500View";
viewModel = new Error500Model();
}
else if (httpCode == 404)
{
viewName = "Error404View";
viewModel = new Error404Model();
}
else if (httpCode == 401)
{
viewName = "Error401View";
viewModel = new Error401Model();
}
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
filterContext.Result = new ViewResult
{
ViewName = viewName,
MasterName = Master,
ViewData = viewModel,
TempData = filterContext.Controller.TempData
};
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = httpCode;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
Затем вы "украшаете" действия своего контроллера этим атрибутом:
[HandleManyErrors]
public ActionResult DoSomethingBuggy ()
{
// ...
}
Мне удалось решить это очень простым способом. Я хотел показать пользовательскую страницу для вошедших в систему пользователей ("у вас нет разрешения, бла-бла...") и перенаправить неаутентифицированных пользователей на страницу входа (поведение по умолчанию). Поэтому я реализовал собственный AuthorizeAttribute (скажем, CustomAuthorizeAttribute) с методом HandleUnauthorizedRequest, перезаписанным таким образом, чтобы при аутентификации пользователя я устанавливал свойство Result аргумента filterContext с помощью ViewResult (в папке Shared) с именем AccessDenied.aspx
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
}
}
Тогда вы должны использовать этот новый атрибут вместо этого. С уважением.
Если вы используете ASP.NET MVC, вы, скорее всего, будете использовать IIS, так почему бы просто не настроить IIS для использования настраиваемой страницы ошибок 401 для этого веб-приложения / виртуального каталога?
В одном из моих проектов я использую код от uvita.
У меня есть ASP.NET MVC2, и я использую аутентификацию Active Directory без страницы входа. У меня есть страница NoAuth.aspx, которая использует главную страницу сайта, интегрировать макет веб-приложения.
Это web.config.
<system.web>
<authentication mode="Windows" />
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
<providers>
<clear />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider"
applicationName="/" />
</providers>
</roleManager>
</system.web>
Новый класс CustomAutorizeAttribute
using System.Web.Mvc;
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
filterContext.Result = new ViewResult { ViewName = "NoAuth"};
}
}
}
и контроллер
[CustomAuthorize(Roles = "ADRole")]
public class HomeController : Controller
{
public HomeController()
{
}
}