EDIT:
я писал выше ответ уже давно, и теперь я считаю, что отправка 403 не является правильным способом пойти. 403 имеет несколько иной смысл, и его просто не следует использовать. Это исправляется атрибут с использованием 401. Он отличается только в дополнительной context.HttpContext.Response.End()
Http401Result и другой код HTTP:
public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
private class Http401Result : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
// Set the response code to 401.
context.HttpContext.Response.StatusCode = 401;
context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue);
context.HttpContext.Response.End();
}
}
private readonly bool _authorize;
public OptionalAuthorizeAttribute()
{
_authorize = true;
}
//OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller.
//That is why parameter is introduced.
public OptionalAuthorizeAttribute(bool authorize)
{
_authorize = authorize;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//When authorize parameter is set to false, not authorization should be performed.
if (!_authorize)
return true;
var result = base.AuthorizeCore(httpContext);
return result;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
//Ajax request doesn't return to login page, it just returns 401 error.
filterContext.Result = new Http401Result();
}
else
base.HandleUnauthorizedRequest(filterContext);
}
}
OLD ОТВЕТ:
Хотя мне нравятся идеи, размещенные в других ответах (которые я имел идея о более раннем), мне нужны образцы кода. Вот они:
Измененный атрибут авторизовать:
public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
private class Http403Result : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
// Set the response code to 403.
context.HttpContext.Response.StatusCode = 403;
context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue);
}
}
private readonly bool _authorize;
public OptionalAuthorizeAttribute()
{
_authorize = true;
}
//OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller.
//That is why parameter is introduced.
public OptionalAuthorizeAttribute(bool authorize)
{
_authorize = authorize;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//When authorize parameter is set to false, not authorization should be performed.
if (!_authorize)
return true;
var result = base.AuthorizeCore(httpContext);
return result;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
//Ajax request doesn't return to login page, it just returns 403 error.
filterContext.Result = new Http403Result();
}
else
base.HandleUnauthorizedRequest(filterContext);
}
}
HandleUnauthorizedRequest
переопределяется, поэтому он возвращает Http403Result
при использовании Ajax. Http403Result
изменяет StatusCode на 403 и возвращает сообщение пользователю в ответ. В атрибуте есть дополнительная логика (параметр authorize
), потому что я включаю [Authorize]
в базовом контроллере и отключите его на некоторых страницах.
Другая важная часть - глобальная обработка этого ответа на стороне клиента. Это то, что я поместил в Site.Master:
<script type="text/javascript">
$(document).ready(
function() {
$("body").ajaxError(
function(e,request) {
if (request.status == 403) {
alert(request.responseText);
window.location = '/Logout';
}
}
);
}
);
</script>
I место глобальный обработчик ошибок Ajax и когда-либо $.post
терпит неудачу с ошибкой 403 ответное сообщение будет предупрежден и пользователь перенаправляется на страницу выхода из системы. Теперь мне не нужно обрабатывать ошибку в каждом запросе $.post
, потому что он обрабатывается глобально.
Почему 403, а не 401? 401 обрабатывается внутри с помощью инфраструктуры MVC (поэтому перенаправление на страницу входа выполняется после неудачной авторизации).
Что вы думаете об этом?
Не будет ли проведен его сеанс после 20 минут бездействия? Ваше приложение перенаправляется на другую страницу? – Raja
@Raja: состояние входа в систему истекает через некоторое время, и я спрашиваю, как справиться с этой ситуацией :) Да, он перенаправляется на страницу входа. – LukLed