2010-12-16 153 views
31

当验证用户没有权限时,Asp.net MVC2会重定向到登录页面response 302Asp.net MVC授权属性,重定向到自定义“无权限”页面

我想分成两个行动

  1. 如果用户没有通过验证,然后做它,重定向到登录页面。
  2. 如果用户已通过身份验证但没有必需的权限,则返回相应的http状态码,并且不显示权利花花白页面。

有没有办法做到这一点?或者我在授权和表单身份验证方面做错了什么?我唯一能想到的方式就是编写自定义的授权属性,这是我想避免的。

+2

哈哈“没有权利的家伙”页...大声笑 – 2010-12-16 04:43:45

回答

9

你可以写一个自定义的授权属性,在AuthorizeCore方法,如果用户没有通过验证回报HttpUnauthorizedResult,如果他被验证,但不执行的角色,你想一些其他的动作。请注意,如果您返回401状态码,则FormsAuthentication框架将最终使用302重定向到登录页面。

+4

但是...你只能从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

+1

是的,你说得对。 – hellangle 2011-07-22 04:20:55

+0

@ReinierDG那么,如何使用AuthorizeAttribute来实现它? – Bellash 2013-11-20 09:53:33

7

正如Customizing authorization in ASP.NET MVC建议,你可以继承的AuthorizeAttribute拦截认证 - 丁 - 未经授权的情况,并用重定向替换结果。

+0

这对于授权缓存结果尤其更好。 – 2012-02-26 14:41:49

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)根据您的具体需求。另外一个名为'UnAuthorized'的视图应该放在MVC引擎可以找到的地方。然后,它可以在一个控制器类(在@ hellangle的回答指出)或操作方法可以使用:

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

} 

为了提供关于各种控制器类和操作方法不同的访问控制策略,实现了用于CustomizedAuthorizeAttribute构造它接受表示访问控制信息的参数,然后相应地实例化CustomizedAuthorizeAttribute类。