Атрибут просит пользователя войти в систему вместо доступа отказано? - PullRequest
7 голосов
/ 30 июля 2010

Обновлено: Благодаря помощи здесь я создал следующее решение:

public class CustomAuthorize : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs
        // If user is not logged in prompt
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
        // Otherwise deny access
        else
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary {
                {"controller", "Account"},
                {"action", "NotAuthorized"}
            });
        }
    }
}
<Ч />

Я начал с NerdDinner и использую FormsAuthentication с ActiveDirectory в качестве поставщика членства. Я добавил поддержку ролей через мою базу данных с помощью Global.asax & AccountController (ниже).

Так что теперь в моем контроллере мой атрибут Authorize установлен только на роли администратора (ниже). Мой вошедший в систему пользователь является автором. Когда я нажимаю удалить, он просит меня войти, хотя я уже сделал это. Где я могу разместить логику для возврата к просмотру запрещенного доступа?

Global.asax.cs

    protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie == null || authCookie.Value == "")
        {
            return;
        }

        FormsAuthenticationTicket authTicket = null;

        try
        {
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        }
        catch
        {
            return;
        }

        if (Context.User != null)
        {
            string[] roles = authTicket.UserData.Split(new char[] { ';' });
            Context.User = new GenericPrincipal(Context.User.Identity, roles);
        }
    }

AccountController.cs

    [HttpPost]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
        Justification = "Needs to take same parameter type as Controller.Redirect()")]
    public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
    {

        if (!ValidateLogOn(userName, password))
        {
            ViewData["rememberMe"] = rememberMe;
            return View();
        }

        // Make sure we have the username with the right capitalization
        // since we do case sensitive checks for OpenID Claimed Identifiers later.
        userName = this.MembershipService.GetCanonicalUsername(userName);

        // Lookup user's (CWID) appropriate access level
        string accessLevel = userRepository.FindUserByUserName(userName).AccessLevel.LevelName;

        FormsAuthenticationTicket authTicket = new
                        FormsAuthenticationTicket(1, //version
                        userName, // user name
                        DateTime.Now,             //creation
                        DateTime.Now.AddMinutes(30), //Expiration
                        rememberMe, //Persistent
                        accessLevel); // hacked to use roles instead

        string encTicket = FormsAuthentication.Encrypt(authTicket);
        this.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));

        if (!String.IsNullOrEmpty(returnUrl))
        {
            return Redirect(returnUrl);
        }
        else
        {
            return RedirectToAction("Index", "Home");
        }
    }

SpotlightController.cs

    [Authorize(Roles="Admin")]
    public ActionResult Delete(int id)

Ответы [ 3 ]

5 голосов
/ 30 июля 2010

Вот что делает AuthorizeAttribute "из коробки": он проверяет, авторизован ли текущий пользователь для текущего запроса, и возвращает HHTP 401 / UNAUTHORIZED, если это не так, либо потому, что он не вошел в систему.или вообще отсутствуют в списке авторизованных пользователей / ролей для текущего запроса.

Модуль HTTP аутентификации веб-форм видит этот ответ 401, перехватывает его и превращает в HTTP 302.(перенаправление) ответ на страницу входа , если в логине web.config настроен атрибут loginUrl.Обычно считается, что если пользователю отказано в доступе к сайту из-за того, что он не вошел в систему, но следующее, что он захочет сделать, - это войти в систему.

Поскольку вы хотите перенаправить в другое место,Предложение Хэла о переопределении HandleUnauthorizedRequest и перенаправлении не является необоснованным.Просто помните, что если вы все еще хотите, чтобы неаутентифицированные пользователи видели страницу входа (в отличие от аутентифицированных, но не в списке разрешенных пользователей / ролей), вам придется добавить логику для этого.Я бы посоветовал против идеи переопределения AuthorizeCore или OnAuthorization;ни один из них на самом деле не решает проблему, и их гораздо проще испортить, чем HandleUnauthorizedRequest.

2 голосов
/ 30 июля 2010

Полагаю, вы могли бы извлечь из AuthorizeAttribute, а затем переопределить HandleUnauthorizedRequest и поместить туда свою собственную логику перенаправления.

Спасибо,

Hal

1 голос
/ 30 июля 2010

В качестве альтернативы вы можете переопределить атрибут Authorize. Вы должны переопределить метод OnAuthorization и получить результат от метода AuthorizeCore из своей базы. На основании этого результата вы можете выдать исключение или пользовательское исключение (т. Е. Может быть пользовательское исключение безопасности, которое регистрирует состояние) прямо из OnAuthirziation.

...