Как мне открыть страницу неавторизованных пользователей, если пользователь не находится в Авторизованных ролях? - PullRequest
40 голосов
/ 24 февраля 2010

Я использую атрибут Authorize следующим образом:

[Authorize (Roles="Admin, User")]
Public ActionResult Index(int id)
{
    // blah
}

Когда пользователь не в указанных ролях, я получаю страницу с ошибкой (ресурс не найден). Поэтому я добавляю также атрибут HandleError.

[Authorize (Roles="Admin, User"), HandleError]
Public ActionResult Index(int id)
{
    // blah
}

Теперь он переходит на страницу Логин , если пользователь не в указанных ролях.

Как заставить его перейти на страницу Несанкционированный вместо страницы входа в систему, когда пользователь не выполняет одну из требуемых ролей? И если возникает другая ошибка, как я могу отличить эту ошибку от неавторизованной ошибки и обработать ее по-другому?

Ответы [ 5 ]

27 голосов
/ 24 февраля 2010

Добавьте что-то подобное в ваш web.config:

<customErrors mode="On" defaultRedirect="~/Login">
     <error statusCode="401" redirect="~/Unauthorized" />
     <error statusCode="404" redirect="~/PageNotFound" />
</customErrors>

Вы, очевидно, должны создать маршруты, действия и представления /PageNotFound и /Unauthorized.

РЕДАКТИРОВАТЬ : Извините, я, видимо, не совсем понял проблему.

Проблема заключается в том, что при выполнении фильтра AuthorizeAttribute он решает, что пользователь не соответствует требованиям (он / она может войти в систему, но не выполняет правильную роль). Поэтому он устанавливает код состояния ответа на 401. Он перехватывается модулем FormsAuthentication, который затем выполняет перенаправление.

Я вижу две альтернативы:

  1. Отключить defaultRedirect.

  2. Создайте свой собственный IAuthorizationFilter. Получите из AuthorizeAttribute и переопределите HandleUnauthorizedRequest. В этом методе, если пользователь аутентифицирован, выполните перенаправление в / Unauthorized

Мне тоже не нравится: функциональность defaultRedirect хороша, а не то, что вы хотите реализовать самостоятельно. Второй подход приводит к тому, что пользователю предоставляется визуально правильная страница «Вы не авторизованы», но коды состояния HTTP не будут иметь желаемого значения 401.

Я недостаточно знаю о HttpModules, чтобы сказать, можно ли это обойти с помощью терпимого взлома.

РЕДАКТИРОВАТЬ 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.

7 голосов
/ 24 февраля 2010

Вы можете сделать это двумя способами:

  1. Укажите ошибку атрибута HandleError и укажите вид, который должен отображаться:

    [HandleError (ExceptionType = typeof (UnAuthorizedException), View = "UnauthorizedError")]

Вы можете указать несколько различных типов исключений и представлений

  1. Создайте собственный ActionFilter, проверьте его на наличие учетных данных и перенаправьте на контроллер, если пользователь не авторизован .: http://web.archive.org/web/20090322055514/http://msdn.microsoft.com/en-us/library/dd381609.aspx
4 голосов
/ 03 декабря 2011

Возможно, код состояния 403 больше подходит для вашего вопроса (пользователь определен, но его учетная запись недостаточно привилегирована) 401 для случая, когда вы не знаете, какие привилегии имеет пользователь.

3 голосов
/ 24 февраля 2010

И HttpUnauthorizedResult (это как реальное использование AuthorizeAtrribute) просто устанавливает StatusCode на 401. Поэтому, вероятно, вы можете настроить страницу 401 в IIS или пользовательские страницы ошибок в web.config.Конечно, вы также должны убедиться, что доступ к вашей пользовательской странице ошибок не требует авторизации.

0 голосов
/ 29 сентября 2017

Просто переопределите метод HandleUnauthorizedRequest AuthorizeAttribute. Если этот метод вызывается, но пользователь прошел проверку подлинности, вы можете перенаправить его на страницу «не авторизован».

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { Area = "", Controller = "Error", Action = "Unauthorized" }));
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}
...