【问题标题】:ASP.Net MVC: Can the AuthorizeAttribute be overriden?ASP.Net MVC:可以覆盖授权属性吗?
【发布时间】:2009-02-10 15:23:54
【问题描述】:

我当前的项目是一个使用 ASP.Net MVC 构建的内部 Web 应用程序,我正在向其中添加身份验证。我有一个预先构建的 HTTPModule,它创建了一个具有适当角色的 IPrincipal。如果用户未通过身份验证,我将获得一个角色为“Public”的用户对象

由于这是一个内部应用程序,大多数页面都是私有的,只有“管理员”角色可以查看。因为我有一个基本控制器,所以我可以这样做:

[Authorize(Roles="Admin")]
public abstract class MyControllerBase : Controller
{
    ...
}

我有一个问题,因为某些操作可以在公共网站上查看,如果我将它们归为这样:

[Authorize(Roles="Public")]
public class LoginController : MyController
{
    public ActionResult Index()
    {

    }
}

由于用户未通过身份验证,页面无法加载。似乎“继承的类上忽略了公共角色。有谁知道这些角色是否可以被继承的类覆盖?

我还试图避免将所有控制器归为 Roles="Admin"

谢谢,基思。

【问题讨论】:

    标签: c# asp.net asp.net-mvc


    【解决方案1】:

    您可以从 AuthorizeAttribute 派生新属性并覆盖 OnAuthorization 方法,然后应用您的自定义属性而不是 Authorize。下面是来自我的一个自定义属性的 OnAuthorization 方法,如果权限不够,它会重定向到错误页面,而不是重定向到登录页面。

    不过,我不确定这会给你带来什么。当你用属性装饰你的类时,大概你必须同时允许 Admin 和 Public (那么你在限制谁,因为 Public 是没有经过身份验证的人?)。然后,您必须装饰每个需要单独限制为 Admin 的控制器方法,因为 class 属性将允许访问。您可以使用常规 Authorize 属性来实现此行为,只需装饰那些非公开可用的方法(或没有公开可用方法的类)。

    我想你可以检查你的属性,看看被调用的方法是否也用属性修饰,然后简单地批准授权,这将有效地将授权推迟到方法级别。您可能必须查看 AuthorizationContext 上的 RouteData 以获取操作并使用反射来尝试根据参数和请求类型找到适当的方法。

        public override void OnAuthorization( AuthorizationContext filterContext )
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException( "filterContext" );
            }
    
            if (AuthorizeCore( filterContext.HttpContext ))
            {
                SetCachePolicy( filterContext );
            }
            else if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                // auth failed, redirect to login page
                filterContext.Result = new HttpUnauthorizedResult();
            }
            else
            {
                ViewDataDictionary viewData = new ViewDataDictionary();
                viewData.Add( "Message", "You do not have sufficient privileges for this operation." );
                filterContext.Result = new ViewResult { MasterName = this.MasterName, ViewName = this.ViewName, ViewData = viewData };
            }
    
        }
    
        protected void SetCachePolicy( AuthorizationContext filterContext )
        {
            // ** IMPORTANT **
            // Since we're performing authorization at the action level, the authorization code runs
            // after the output caching module. In the worst case this could allow an authorized user
            // to cause the page to be cached, then an unauthorized user would later be served the
            // cached page. We work around this by telling proxies not to cache the sensitive page,
            // then we hook our custom authorization code into the caching mechanism so that we have
            // the final say on whether a page should be served from the cache.
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge( new TimeSpan( 0 ) );
            cachePolicy.AddValidationCallback( CacheValidateHandler, null /* data */);
        }
    

    【讨论】:

    • 感谢您的建议,我认为创建自己的授权形式将是可行的方法。我这样做是因为该应用程序是内部的,它还在 IFrame 的公共网站上显示地图。所以默认只有管理员访问权限,一些控制器可以公开查看。
    【解决方案2】:

    最后,我认为我的答案就在问题中。我没有将 Authorize 属性放在我的基本控制器上,而是派生了一个新的 AdminBaseController。

    [HandleError]
    public abstract class MyControllerBase : Controller
    {
        ...
    }
    
    [Authorize(Roles="Admin")]
    public abstract class AdminControllerBase : MyControllerBase
    {
        ....
    }
    

    现在任何需要身份验证的控制器都可以从 AdminControllerBase 派生,而我的公共控制器可以从 MyControllerBase 派生。 OO 来救援。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-03
      相关资源
      最近更新 更多