Как отобразить страницу пользовательских ошибок для результата Http 401?

У меня есть контроллер с атрибутом Authorize следующим образом:

[Authorize(Roles = "Viewer")]
public class HomeController : Controller
{
   //...
}

и у моего web.config есть customErrors, как показано ниже:

<customErrors mode="On">
      <error statusCode="401" redirect="notauthorized.html"/>
  </customErrors>

Когда я пытаюсь вызвать действие на домашнем контроллере с помощью неавторизованной роли, я просто получаю пустую страницу. Я не перенаправляюсь на пользовательскую страницу. Любые идеи?

Ответ 1

Я понимаю, что этот вопрос немного стар, но это может помочь кому-то.

Для 401 вы, вероятно, увидите стандартную страницу 401 Unauthorized, даже если вы добавили 401 в раздел customerrors в вашем web.config. Я прочитал, что при использовании IIS и проверки подлинности Windows проверка происходит до того, как ASP.NET даже увидит запрос, поэтому вы видите пустую страницу на Cassini, а на IIS - 401.

В моем проекте я отредактировал файл Global.asax, чтобы перенаправить на маршрут, который я создал для ошибок 401, отправив пользователя в представление "Несанкционированное видеть это".

В Global.asax:

    void Application_EndRequest(object sender, System.EventArgs e)
    {
        // If the user is not authorised to see this page or access this function, send them to the error page.
        if (Response.StatusCode == 401)
        {
            Response.ClearContent();
            Response.RedirectToRoute("ErrorHandler", (RouteTable.Routes["ErrorHandler"] as Route).Defaults);
        }
    }

и в Route.config:

        routes.MapRoute(
        "ErrorHandler",
        "Error/{action}/{errMsg}",
        new { controller = "Error", action = "Unauthorised", errMsg = UrlParameter.Optional }
        );

и в контроллере:

    public ViewResult Unauthorised()
    {
        //Response.StatusCode = 401; // Do not set this or else you get a redirect loop
        return View();
    }

Ответ 2

Посмотрите tvanfosson ответ от этот очень похожий вопрос. Это то, что я делаю (спасибо tvanfosson), так что теперь я просто должен сказать:

[MyAuthorize(Roles="SuperAdmin",ViewName="AccessDenied")]
public class SuperAdminController : Controller
...

Если пользователь не находится в роли, он получит это представление, указанное ViewName.

Примечание. пустая страница исходит от Cassini, если вы переместите приложение на реальный сервер IIS, вы увидите 401.

Ответ 3

Стандартный подход, насколько мне известно, состоит в том, чтобы иметь простой контроллер ошибок, который обрабатывает входящие запросы и выводит соответствующее представление в зависимости от того, какой код httpstatus был возвращен... что-то вроде этого:

  public class ErrorController : Controller
{

    [AcceptVerbs(HttpVerbs.Get)]
    public ViewResult Index()
    {

        //Check if the statuscode is HttpStatusCode.NotFound;
         if(Response.StatusCode == 401)
             return View("NotAuthorised");
        return View();
    }
}

а затем укажите действие перенаправления в вашем webconfig:

<customErrors mode="On" defaultRedirect="~/Error" />

Ответ 4

Также вы можете создать свой собственный настраиваемый атрибут авторизации и настроить собственный маршрут для перенаправления пользователей на свою страницу.

Вот пример моего проекта:

/*../controllers/CustomAuthorizationAttribute.cs  */
public class CustomAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
    void IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)
    {
        string session = filterContext.HttpContext.Session["id"] != null ? filterContext.HttpContext.Session["id"].ToString() : null;
        if ( string.IsNullOrEmpty(session) )
        {
            // Unauthorized!
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "action", "Create" }, { "controller", "Sessions" } 
                    //,{ "parameterName", "YourParameterValue" }
                }
            );
        }
    }
}

и вы добавляете свой "флаг" в свой контроллер действий, как этот

/*../controllers/ReportsController.cs  */
public class ReportsController : Controller
{
    [CustomAuthorizationAttribute]
    public ActionResult Index()
    {
        //do something
    }
}