Ответ 1
Добавьте что-то вроде этого в свой web.config:
<customErrors mode="On" defaultRedirect="~/Login">
<error statusCode="401" redirect="~/Unauthorized" />
<error statusCode="404" redirect="~/PageNotFound" />
</customErrors>
Очевидно, вы должны создать маршруты, действия и представления /PageNotFound
и /Unauthorized
.
РЕДАКТИРОВАТЬ: Извините, я, по-видимому, не понял эту проблему полностью.
Проблема заключается в том, что при выполнении фильтра AuthorizeAttribute
он решает, что пользователь не соответствует требованиям (он/она может быть зарегистрирован, но не в правильной роли). Поэтому он устанавливает код состояния ответа 401. Это перехватывается модулем FormsAuthentication
, который затем выполняет перенаправление.
Я вижу две альтернативы:
-
Отключить defaultRedirect.
-
Создайте свой собственный
IAuthorizationFilter
. Вывести изAuthorizeAttribute
и переопределить HandleUnauthorizedRequest. В этом методе, если пользователь аутентифицирован, перенаправляет на /Unauthorized
Мне тоже не нравится: функция defaultRedirect хороша, а не то, что вы хотите реализовать самостоятельно. Второй подход приводит к тому, что пользователь получает визуально правильную "Вы не авторизована" -страница, но коды состояния HTTP не будут желательными 401.
Я не знаю достаточно о HttpModules, чтобы сказать, можно ли обойти это с допустимым взломом.
EDIT 2: Как реализовать свой собственный IAuthorizationFilter следующим образом: загрузите код MVC2 из CodePlex и "заимствуйте" код для AuthorizeAttribute. Измените метод OnAuthorization, чтобы он выглядел как
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
// Is user logged in?
else if(filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// Redirect to custom Unauthorized page
filterContext.Result = new RedirectResult(unauthorizedUrl);
}
else {
// Handle in the usual way
HandleUnauthorizedRequest(filterContext);
}
}
где unauthorizedUrl
является либо свойством фильтра, либо считывается из Web.config.
Вы также можете наследовать от AuthorizeAttribute и переопределить OnAuthorization
, но в итоге вы напишите пару частных методов, которые уже находятся в AuthorizeAttribute.