пользовательские ошибки для 401.2 в ASP.NET

Я успешно реализовал авторизацию на основе ролей в ASP.NET. Когда у человека нет нужной роли, он видит страницу с ошибкой 401.2 не авторизован.

Чего я хотел бы добиться сейчас, так это создать пользовательскую страницу 401 в своем приложении и перенаправить ее туда с помощью настроек в файле web.config. Я пробовал это:

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
    <error statusCode="401" redirect="NoAccess.htm" />
</customErrors>

Но это не поймать. Должен ли я вместо этого переопределить его в IIS? Я надеюсь, что нет, поскольку это затруднит развертывание вещей.


person Nyla Pareska    schedule 13.01.2010    source источник


Ответы (4)


Недавно я столкнулся с той же проблемой, и оказалось, что это одна из особенностей при использовании проверки подлинности Windows.

Джошуа Фланаган недавно создал хороший HttpModule, который будет учитывать раздел customErrors в файле web.config и перенаправление на страницу с ошибкой 401.

Ключом к решению является перехват события EndRequest жизненного цикла страницы, проверка кода состояния 401, а затем выполнение пользовательской страницы.

Переносимость HttpModule хороша тем, что позволяет повторно использовать решение и сохраняет ваш Global.asax в чистоте, но ничто не мешает вам связать событие EndRequest в Global.asax с его кодом, если вы действительно этого хотите.

Если вы используете ASP.NET MVC, решение не такое элегантное.

person Ryan Rivest    schedule 06.02.2010

Если вы не хотите добавлять HttpModule

в веб.конфигурации

<system.web>
    <customErrors mode="On" defaultRedirect="~/MyController/MyErrorAction/" redirectMode="ResponseRedirect">
      <error statusCode="401" redirect="~/MyController/MyErrorAction/" />
    </customErrors>

в global.asax.cs

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;

        if (application.Response.StatusCode != 401 || !application.Request.IsAuthenticated) return;

        application.Response.ClearContent();

        //You can replace the piece below is to redirect using MVC, or your can replace all this with application.Server.Execute(yourPage);
        IController errorController = new SharedController();
        var rd = new RouteData();
        rd.Values.Add("controller", "MyController");
        rd.Values.Add("action", "MyErrorAction");
        rd.Values.Add("value", "You or your user group do not have permissions to use the address: " + Request.Url.PathAndQuery);

        errorController.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
        HttpContext.Current.Server.ClearError();
    }
person Junior Mayhé    schedule 17.09.2012
comment
Действительно ли правильно отрицание IsAuthenticated? Разве не должно быть наоборот, т.е. если аутентифицированный => возврат из метода? - person aeliusd; 26.01.2015
comment
Кажется, этот метод не работает, если на странице есть переменные сеанса. Я получаю это, когда он пытается выполнить страницу Object reference not set to an instance of an object - person BStill; 07.06.2018

Вот независимый от MVC вариант:

В Web.config

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
    <error statusCode="401" redirect="NoAccess.htm" />
</customErrors>

В Global.asax.cs

protected void Application_EndRequest(object sender, EventArgs e)
{
    HttpApplication application = (HttpApplication)sender;

    if (application.Response.StatusCode != 401 || !application.Request.IsAuthenticated) return;

    var customErrors = (CustomErrorsSection)ConfigurationManager.GetSection("system.web/customErrors");

    var accessDeniedPath = customErrors.Errors["401"] != null ? customErrors.Errors["401"].Redirect : customErrors.DefaultRedirect;
    if (string.IsNullOrEmpty(accessDeniedPath))
        return; // Let other code handle it (probably IIS).

    application.Response.ClearContent();
    application.Server.Execute(accessDeniedPath);
    HttpContext.Current.Server.ClearError();
}
person Jeremy Cook    schedule 29.08.2013

Вот что хорошо сработало для меня.

Global.asax -

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        if (Response.StatusCode == 401 && Request.IsAuthenticated)
        {
            Response.StatusCode = 303;
            Response.Clear();
            Response.Redirect("~/AccessDenied.html");
            Response.End();
        }
    }

Web.config -

  <system.web>
    <customErrors mode="On">
      <error statusCode="401" redirect="AccessDenied.html"/>
    </customErrors>
    <authentication mode="Windows"/>
  </system.web>
  <location path="AccessDenied.html">
    <system.web>
      <authorization>
        <allow roles="*"/>
      </authorization>
    </system.web>
  </location>
  <location path=".">
    <system.web>
      <authorization>
        <allow roles="YourADGroup"/>
        <deny users="*" />
      </authorization>
    </system.web>
  </location>

Это касается и двойного 401 перед выпуском 200. Также обходит надоедливое всплывающее окно аутентификации Firefox.

person Ditti    schedule 14.05.2015