Asp.net mvc 4 防止放任

Asp.net mvc 4 防止放任,asp.net-mvc-4,Asp.net Mvc 4,我有一个全局标记为[授权]的基本控制器。有没有办法通过简单地添加[AllowAnonymous]属性来防止继承它的控制器覆盖授权要求 下面是我的具体场景:我有三个基本控制器:一个用于匿名用户,两个用于登录用户,这两个控制器都用[Authorize]全局修饰。创建的每个新控制器都从基本的三个控制器之一继承,具体取决于所需的功能。其中一个[授权]控制器包含绝对不应由匿名用户运行的“高度安全”功能。继承此“安全”基本控制器的开发人员意外地用[AllowAnonymous]修饰了一些方法,这使匿名用户能

我有一个全局标记为[授权]的基本控制器。有没有办法通过简单地添加[AllowAnonymous]属性来防止继承它的控制器覆盖授权要求

下面是我的具体场景:我有三个基本控制器:一个用于匿名用户,两个用于登录用户,这两个控制器都用[Authorize]全局修饰。创建的每个新控制器都从基本的三个控制器之一继承,具体取决于所需的功能。其中一个[授权]控制器包含绝对不应由匿名用户运行的“高度安全”功能。继承此“安全”基本控制器的开发人员意外地用[AllowAnonymous]修饰了一些方法,这使匿名用户能够潜在地访问基本控制器中的“安全”功能。这是在测试中发现的,但我认为这将是一个好主意,以防止这种类型的错误,我想知道是否有一个简单的方法来做到这一点。目前,我已将所有代码放入secure base controller中,并将其包装在以下代码块中:

if (Request.IsAuthenticated)
{
    // do stuff
}
else
{
    // redirect to login page, basically simulating what [Authorize] does
}
以上内容满足了我的要求,但它首先有点违背了全球[授权]装饰的目的。我的设想大致如下:

[Authorize(AllowAnonymousOverride=false)] // this doesn't exist, but might be helpful

是否有更好的方法来实现此功能?

首先,您似乎有一个带有某些方法的控制器,然后您的方法是继承它,以便公开相同的方法。我想知道有两个或更多的控制器公开相同的数据有什么意义。这是开发人员的错误,或者更确切地说,这是您方法中的自定义例程

然后,您希望有一个阻止其他属性的属性,但这在该语言或mvc框架中显然是不可能的

第三,有人编写了一个没有单元测试的控制器,或者可能有测试,但是没有人验证这些测试,因此在手动测试阶段发现了问题。这表明问题更为广泛,不仅限于继承——假设您的开发人员编写了一个控制器,该控制器没有继承任何内容,并且由于允许匿名标记而仍然公开一些关键数据。然后呢?即使您对原始问题有补救措施,也无法抓住新的可能问题


我的建议是在构建后事件中附加一个自定义分析器,该分析器扫描所有可能的控制器,列出所有匿名和受限操作,并将其与以前生成的列表进行比较。如果有更改,则会创建一个警报,必须有人手动解决该问题,方法是批准新创建的操作或拒绝更改,因为引入了错误。

正确的方法是派生您自己的属性。默认属性如下所示:

namespace System.Web.Mvc
{
  public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
  {
    public virtual void OnAuthorization(AuthorizationContext filterContext)
    {
      if (filterContext == null)
      {
        throw new ArgumentNullException("filterContext");
      }

      if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
      {
        throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
      }

      // This is the Important part..
      bool flag = filterContext.ActionDescriptor
                   .IsDefined(typeof(AllowAnonymousAttribute), true)
        || filterContext.ActionDescriptor.ControllerDescriptor
            .IsDefined(typeof(AllowAnonymousAttribute), true);

      if (flag)
      {
        return;
      }

      if (this.AuthorizeCore(filterContext.HttpContext))
      {
        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        cache.SetProxyMaxAge(new TimeSpan(0L));
        cache.AddValidationCallback(
          new HttpCacheValidateHandler(this.CacheValidateHandler), null);
        return;
      }
      this.HandleUnauthorizedRequest(filterContext);
    }
  }
}
衍生出你自己的:

  public class CustomAuthorizeAttribute : AuthorizeAttribute
  {
    public bool IsAllowAnonymousEnabled { get; set; }

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

      if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
      {
        throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
      }

      // This is the Important part..
      bool flag = IsAllowAnonymousEnabled
        && (filterContext.ActionDescriptor
             .IsDefined(typeof(AllowAnonymousAttribute), true)
        || filterContext.ActionDescriptor.ControllerDescriptor
            .IsDefined(typeof(AllowAnonymousAttribute), true));

      if (flag)
      {
        return;
      }

      if (this.AuthorizeCore(filterContext.HttpContext))
      {
        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        cache.SetProxyMaxAge(new TimeSpan(0L));
        cache.AddValidationCallback(
          new HttpCacheValidateHandler(this.CacheValidateHandler), null);
        return;
      }
      this.HandleUnauthorizedRequest(filterContext);
    }
  }
用法:

[CustomAuthorizeAttribute(IsAllowAnonymousEnabled = false)]
public class MyController : Controller
{
  [AllowAnonymous]
  public ActionResult Index()
  {
    // This will still execute Authorization regardless of [AllowAnonymous]

    return View();
  }
}

您不能调用
base.OnAuthorization()
,因为它将允许
AllowAnonymous

您始终可以将base controller属性更改为Allowanonymous@qamar-事实上,我想做相反的事。我不希望匿名用户能够在基本控制器中运行代码。可能是@ocanal的重复-我的问题措辞一定很糟糕,因为你的解释也与我的意图相反。我添加了一个示例,说明了我要查找的内容以及原因。@ocanal-您提供的链接是如何覆盖authorize属性。这个问题是不同的,因为我问的是相反的问题:如何防止覆盖authorize属性。Erik的回答似乎回答了这个问题。你的观点是:1:它没有公开类似的方法,而是基本控制器中的“安全”功能是在“受保护的覆盖void OnActionExecuting”中完成的。2:我相信这就是失败的原因——假设[授权]可以保证安全,但它不能。3:编写单元测试可以确保身份验证,也可以使用if(Request.IsAuthenticated)。这看起来正是我想要完成的。你能检查一下逻辑吗?我认为应该是:bool flag=IsAllowAnonymousEnabled&(filterContext…| | filterContext…)