атрибут для метода действия контроллера .net MVC - PullRequest
8 голосов
/ 07 января 2010

По сути, я хочу показать дружеское сообщение, когда кто-то не является частью роли, указанной в моем атрибуте. В настоящее время мое приложение просто выплевывает пользователя обратно на экран входа в систему. Я прочитал несколько постов, в которых говорится о создании пользовательского атрибута, который просто расширяет [AuthorizeAttribute], но я думаю, что для этого должно быть что-то из коробки?

Может кто-нибудь, пожалуйста, указать мне правильное направление, куда мне нужно смотреть, чтобы он не отправлял пользователя в форму входа в систему, а просто отправлял им сообщение "не авторизовано"?

Ответы [ 5 ]

6 голосов
/ 31 августа 2010

Возможно, я немного опоздал с добавлением моего 0,02 доллара, но когда вы создаете свой CustomAuthorizationAttribue, вы можете использовать свойство AuthorizationContext.Result , чтобы указать, куда метод AuthorizeAttribute.HandleUnauthorizedRequest направляет пользователя.

Вот очень простой пример, который позволяет указать URL-адрес, куда следует отправлять пользователя после неудачной авторизации:

public class Authorize2Attribute : AuthorizeAttribute
{
    // Properties

    public String RedirectResultUrl { get; set; }

    // Constructors

    public Authorize2Attribute()
        : base()
    {
    }

    // Overrides

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (String.IsNullOrEmpty(RedirectResultUrl))
            base.HandleUnauthorizedRequest(filterContext);

        else
            filterContext.Result = new RedirectResult(RedirectResultUrl);
    }
}

И если бы я хотел перенаправить пользователя в / Error / Unauthorized, как предлагалось в предыдущем посте:

[Authorize2(Roles = "AuthorizedUsers", RedirectResultUrl = "/Error/Unauthorized")]
public ActionResult RestrictedAction()
{
    // TODO: ...
}
3 голосов
/ 08 января 2010

Я столкнулся с этой проблемой несколько дней назад, и решение немного подробное, но вот важные моменты. В AuthorizeAttribute метод OnAuthorization возвращает HttpUnauthorizedResult, когда авторизация не удалась, что немного затрудняет возврат пользовательского результата.

В итоге я создал класс CustomAuthorizeAttribute и переопределил метод OnAuthorization, чтобы вместо этого выдать исключение. Затем я могу перехватить это исключение с помощью специального обработчика ошибок и отобразить настроенную страницу ошибок вместо возврата 401 (неавторизовано).

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public virtual void OnAuthorization(AuthorizationContext filterContext) {
        if (filterContext == null) {
            throw new ArgumentNullException("filterContext");
        }

        if (AuthorizeCore(filterContext.HttpContext)) {
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
        }
        else {
            // auth failed, redirect to login page
            // filterContext.Result = new HttpUnauthorizedResult();

            throw new HttpException ((int)HttpStatusCode.Unauthorized, "Unauthorized");                
        }
    }
}

, затем в вашем web.config вы можете установить собственные обработчики для определенных ошибок:

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

, а затем реализуйте свой собственный ErrorController для обслуживания пользовательских страниц.

В IIS7 вам нужно обратиться к настройке Response.TrySkipIisCustomErrors = true;, чтобы включить ваши собственные ошибки.

2 голосов
/ 13 мая 2011

Очень похоже на crazyarabian, но я перенаправляю на свою строку, только если пользователь действительно аутентифицирован. Это позволяет атрибуту перенаправлять на стандартную страницу входа, если они в данный момент не вошли в систему, но на другую страницу, если у них нет прав доступа к URL.

public class EnhancedAuthorizeAttribute : AuthorizeAttribute
{
    public string UnauthorizedUrl { get; set; }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        var redirectUrl = UnauthorizedUrl;
        if (filterContext.HttpContext.User.Identity.IsAuthenticated && !string.IsNullOrWhiteSpace(redirectUrl))
        {
            filterContext.Result = new RedirectResult(redirectUrl);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}
2 голосов
/ 07 января 2010

Если вам нужна простота или полный контроль над логикой, вы можете назвать это в своем методе действия:

User.IsInRole("NameOfRole");

Возвращает логическое значение, и вы можете выполнять всю остальную логику в зависимости от этого результата.

Еще один, который я использовал в некоторых случаях:

System.Web.Security.Roles.GetRolesForUser();

Я думаю, что это возвращает строку [], но не цитируйте меня по этому поводу.

EDIT: Пример всегда помогает ...

public ActionResult AddUser()
{
    if(User.IsInRoles("SuperUser")
    {
        return View("AddUser");
    }
    else
    {
        return View("SorryWrongRole");
    }
}

Пока ваш тип возврата "ActionResult", вы можете возвращать любой из принятых типов возврата (ViewResult, PartialViewResult, RedirectResult, JsonResult ...)

0 голосов
/ 07 января 2010

Стандартное поведение состоит в том, что атрибут [Authorize] возвращает HTTP 401. FormsAuthenticationModule (который загружается по умолчанию) перехватывает этот 401 и перенаправляет пользователя на страницу входа. Взгляните на System.Web.Security.FormsAuthenticationModule :: OnLeave в Reflector, чтобы понять, что я имею в виду.

Если вы хотите, чтобы AuthorizeAttribute что-то сделал иным , чем возврат HTTP 401, вам придется переопределить метод AuthorizeAttribute :: HandleUnauthorizedRequest и выполнить там свою собственную логику. В качестве альтернативы просто измените эту часть ~ \ Web.config:

<forms loginUrl="~/Account/LogOn" timeout="2880" />

И сделайте так, чтобы он указывал на другой URL, например ~ / AccessDenied.

...