7

我有一个简单的 ASP.Net MVC 3 应用程序,它有一些控制器和一些很好的操作。

现在,由于这是一个基于用户的应用程序,大多数控制器操作都需要对用户进行身份验证。MVC 使用内置的 Authorize 属性很好地处理了这个问题,您可以使用它来单独装饰控制器和/或操作。

最棒的是您可以将属性仅应用于控制器,并且该给定控制器的所有操作也将应用它 - 节省了大量输入;)

但我有一个控制器,可以说,10 个动作。但我希望其中一项操作不应用 Authorize 属性。

是的,我可以将该属性应用于其他 9 个并将其从控制器中删除,这将完全满足我的需要。但是有没有办法让它应用到控制器并选择排除其中一个动作?

实际上,想要类似...

[!Authorize]或者[NotAuthorize]

我知道我可以创建一个自定义的来完成这项工作,但我想知道是否有内置的方法可以做到这一点?还是我必须将该属性应用于所有其他 9 个操作?

4

2 回答 2

13

请注意,在 ASP.NET MVC 4.0中添加了一个新属性,它正是这样做的:
[AllowAnonymous]

于 2012-07-12T02:02:25.700 回答
2

Phil Haack 最近写了一篇博客文章来处理这个确切的场景:

ASP.NET MVC 3 中的条件过滤器

他的解决方案包括编写一个自定义的“条件过滤器提供程序”,它允许将过滤条件指定给操作方法的属性。

细节和推理在他的帖子里,但是代码比较简单。首先,创建过滤器提供程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

public class ConditionalFilterProvider : IFilterProvider {
  private readonly 
    IEnumerable<Func<ControllerContext, ActionDescriptor, object>> _conditions;

  public ConditionalFilterProvider(
    IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions)
  {

      _conditions = conditions;
  }

  public IEnumerable<Filter> GetFilters(
      ControllerContext controllerContext, 
      ActionDescriptor actionDescriptor) {
    return from condition in _conditions
           select condition(controllerContext, actionDescriptor) into filter
           where filter != null
           select new Filter(filter, FilterScope.Global, null);
  }
}

然后应用它:

IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions = 
    new Func<ControllerContext, ActionDescriptor, object>[] { 

    (c, a) => c.Controller.GetType() != typeof(HomeController) ? 
      new MyFilter() : null,
    (c, a) => a.ActionName.StartsWith("About") ? new SomeFilter() : null
};

var provider = new ConditionalFilterProvider(conditions);
FilterProviders.Providers.Add(provider);
于 2011-11-03T17:48:22.420 回答