8

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

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

ответ

2

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

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

так используя эту логику, мне нужно будет вернуть частичные виды с «дружескими сообщениями» правильно? Невозможно ли охватить весь метод действия с помощью атрибута, который делает то же самое? – Kyle

+0

Я добавил пример выше. Ваш другой вариант, конечно же, написание вашего собственного атрибута, как вы упомянули (что было бы самым чистым, хотя и более жестким для модульного теста), но это определенно не «готовый» подход. –

0

Исключительное поведение в том, что атрибут [Авторизовать] возвращает 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.

3

Я столкнулся с этим вопросом несколько дней назад, и решение немного детализировано, но вот важные бит. В 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;, чтобы включить пользовательские ошибки.

6

Возможно, я немного опоздал на добавление моих $ 0.02, но когда вы создаете свой CustomAuthorizationAttribue, вы можете использовать AuthorizationContext.Result property, чтобы определить, где метод 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/Несанкционированное как было предложено в предыдущем посте:

[Authorize2(Roles = "AuthorizedUsers", RedirectResultUrl = "/Error/Unauthorized")] 
public ActionResult RestrictedAction() 
{ 
    // TODO: ... 
} 
+0

Я сделал аналогичную вещь, но я проверяю, проверен ли пользователь. Это позволяет мне отклонять пользователей из-за того, что они не играют роли, но их не просят войти в систему –

2

Очень похож на 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); 
     } 
    } 
} 
Смежные вопросы