2010-12-16 2 views
31

Asp.net MVC2 перенаправляет на страницу входа с response 302, когда аутентифицированный пользователь не имеет прав.Атрибут Authorize Asp.net MVC, перенаправление на пользовательскую страницу «без прав»

Я хотел бы разделить на два действия

  1. Если пользователь не прошел проверку подлинности, то делать то, что он делает, перенаправление на страницу входа.
  2. Если пользователь аутентифицирован, но не имеет необходимых прав, верните соответствующий код статуса http и покажите страницу прав на чужие страницы.

Есть ли способ сделать это? Или я делаю что-то неправильно с авторизацией и аутентификацией формы? Единственный способ, о котором я могу думать, - написать собственный атрибут authorize, который я хочу избежать.

+2

haha ​​"no rights dude" page ... lol – 2010-12-16 04:43:45

ответ

9

Вы можете написать настраиваемый атрибут authorize и в методе AuthorizeCore, если пользователь не аутентифицирован, возвратите HttpUnauthorizedResult и, если он прошел проверку подлинности, но не выполняет роли, вы хотите выполнить другое действие. Обратите внимание, что если вы вернете код статуса 401, структура FormsAuthentication в конечном итоге перенаправит с 302 на страницу входа.

+4

Но ... вы можете вернуть bool только из AuthorizeCore. Вы должны переопределить OnAuthorization, чтобы вернуть ActionResult – 2012-01-26 17:31:47

+1

@EduardoMolteni, вы можете переопределить метод HandleUnauthorizedRequest, чтобы вернуть нужный результат. – 2012-01-26 17:38:09

18

Вы можете написать пользовательский атрибут фильтра, как это:

public class CustomAuthorizeAttribute : ActionFilterAttribute 
    { 
     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      if (filterContext.HttpContext.User.Identity == null || !filterContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       filterContext.Result = new RedirectResult(System.Web.Security.FormsAuthentication.LoginUrl + "?returnUrl=" + 
       filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.RawUrl)); 
      } 

      //Check user right here 
      if (userNotRight) 
      { 
       filterContext.HttpContext.Response.StatusCode = 302; 
       filterContext.Result = new HttpUnauthorizedResult(); 
      } 
     } 
    } 

и использовать его в контроллере:

[CustomAuthorize] 
public class HomeController : Controller 
{ 

} 
+18

Вы должны использовать AuthorizeAttribute вместо ActionFilterAttribute для авторизации. – ReinierDG 2011-07-06 09:22:14

7

Как было предложено в Customizing authorization in ASP.NET MVC, вы могли бы подкласс AuthorizeAttribute для перехвата аутентификацией-Но- несанкционированный сценарий и заменить результат перенаправлением.

6

Внесите заказ AuthorizeAttribute и добавьте следующее переопределение. Основой является проверка подлинности пользователя, но не авторизация, а затем перенаправление на вашу собственную страницу «Отказано в доступе». Надеюсь это поможет!

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    base.OnAuthorization(filterContext); 

    // Check if user is authenticated and if this action requires authorization 
    if (filterContext.HttpContext.User.Identity.IsAuthenticated 
     && filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute), true) 
     || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AuthorizeAttribute), true)) 
    { 
     List<object> attributes = new List<object>(filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true)); 
     attributes.AddRange(filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true)); 

     // Check all authorzation attributes 
     foreach (var attribute in attributes) 
     { 
      var authAttribute = attribute as AuthorizeAttribute; 
      if (authAttribute != null) 
      { 
       if (!filterContext.HttpContext.User.IsInRole(authAttribute.Roles)) 
       { 
        // User is not authorized so redirect to our access denied error page 
        filterContext.Result = new RedirectToRouteResult(
         new RouteValueDictionary 
          { 
           { "area", "" }, 
           { "controller", "Error" }, 
           { "action", "AccessDenied" } 
          }); 
        break; 
       } 
      } 
     } 
    } 
} 
3

Подобно решениям, предложенным @hellangle и @Andreas, я использовал следующий код, чтобы решить эту проблему:

public class CustomizedAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var userAuthInfo = GetUserAuthInfo(); 

     if (!userAuthInfo.IsAuthenticated()) 
     { 
      filterContext.Result = new RedirectResult(UrlToYourLoginPage); 
      return; 
     } 

     if (!userAuthInfo.IsAuthorized()) 
     { 
      var result = new ViewResult {ViewName = "UnAuthorized"}; 
      result.ViewBag.Message = "Sorry! You are not authorized to do this!"; 
      filterContext.Result = result; 
     } 
    } 
} 

Конечно, вам нужно реализовать информации авторизации пользователя класса и связанные с ними методы (GetUserAuthInfo, IsAuthenticated, IsAuthorized) в соответствии с вашими конкретными потребностями. Кроме того, View, названный 'UnAuthorized', должен быть помещен туда, где может найти двигатель MVC. Тогда он может быть применен на класс контроллера (указал в ответе @ hellangle в), или способе действия:

[CustomizedAuthorizeAttribute] 
public class TargetController : Controller 
{ 
    [CustomizedAuthorizeAttribute] 
    public ActionResult TargetAction() 
    { 
     // Your Code 
    } 

} 

Для того, чтобы обеспечить различные стратегии управления доступом для различных классов контроллеров и методы действий, реализует конструктор CustomizedAuthorizeAttribute класс, который принимает параметр (ы), представляющий информацию управления доступом, а затем соответственно задает класс CustomizedAuthorizeAttribute.

Смежные вопросы