Как обрабатывать исключения безопасности PrincipalPermission

У меня есть простой метод, который защищен

[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")] 
protected void lnkClearCache_Click(object sender, EventArgs e)
{
    ...
}

Если щелкнуть по нему без роли, будет сгенерировано System.Security.SecurityException: Request for principal permission failed., как и ожидалось.

Я использую ELMAH для ведения журнала ошибок, и у меня есть специальное событие ELMAH в файле global.asax для передачи на страницы ошибок способами, сохраняющими коды состояния, которые работают правильно.

private void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args)
{
    var customErrorsSection = GetCustomErrorsSection();       
    var error = args.Entry;

    string statusCode = error.Error.StatusCode.ToString();

    if (statusCode == "0" && error is security exception)
        statusCode = "403";

    var errorSection = customErrorsSection.Errors[statusCode];
    string redirectUrl = errorSection == null ?
            customErrorsSection.DefaultRedirect : errorSection.Redirect;


    RespondWithServerError(error.Id, redirectUrl, statusCode);
}

Это работает хорошо и нормально и перенаправляет на мою страницу с ошибкой, которая работает правильно, однако вместо того, чтобы отображать содержимое, как ожидалось. Я сразу же получаю второй запрос на страницу с ошибкой, но на этот раз с использованием значения customErrorsSection.DefaultRedirect, которое никаким образом не исходит из моего кода.

Насколько я могу судить, это почти так, как если бы .NET вызывал исключение для PrincipalPermission, а затем позволял завершить весь запрос, а затем после завершения запроса отбрасывал ответ приложения и вместо этого отвечал пользовательской ошибкой по умолчанию.

Когда я отлаживаю, я разбиваю 2 отдельных исключения для PrincipalPermission, является ли это просто повторным броском .NET, я не уверен, но мой код .NET никогда не видит 2-й бросок, как и ELMAH. Я всегда получаю один ответ, регистрируется одна ошибка, но URL-адрес, который, наконец, отображается в браузере, является URL-адресом по умолчанию, а не URL-адресом 403, на который я специально перешел server.transferred. Если я просматриваю безопасное /местоположение, я правильно получаю страницу с ошибкой 403.


person Chris Marisic    schedule 28.02.2011    source источник


Ответы (1)


Я точно не знаю, где проблема. Но я использую что-то подобное, и для меня это решение (свернутое) прекрасно работает.

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        Dim er = HttpContext.Current.Error
        If er.GetType.Equals(GetType(System.Security.SecurityException)) Then
            HttpContext.Current.Response.Redirect(FormsAuthentication.LoginUrl & "?ReturnUrl=" & HttpContext.Current.Request.Path)
        End If
    End Sub

Это вне global.asax

Но в некоторых местах я не перенаправляю, а просто использую try и catch исключение безопасности, чтобы показать пользователю, что ему не разрешено выполнять такое действие.

person Luke    schedule 28.02.2011
comment
Что ж, это было совершенно глупо, что каким-то образом ASP.NET волшебным образом заставляет ошибку появляться в ошибке приложения, которая полностью обходит ВСЕ нормальную обработку ошибок. Таким образом, копирование и вставка половины моего метода ErrorLog_Logged дает мне ожидаемые результаты, так как другая часть моей души умирает из-за необходимости делать такие вещи. - person Chris Marisic; 01.03.2011