【问题标题】:ActionFilterAttribute - apply to actions of a specific controller typeActionFilterAttribute - 应用于特定控制器类型的操作
【发布时间】:2010-11-29 05:37:05
【问题描述】:

我正在使用 ActionFilterAttribute 来执行自定义身份验证逻辑。该属性将仅用于包含我的身份验证逻辑的派生 Controller 类。

这是我的控制器,派生自我的自定义控制器类,以及一个示例属性:

public class MyController : CustomControllerBase
{

   [CustomAuthorize(UserType = UserTypes.Admin)]
   public ActionResult DoSomethingSecure()
   {
      return View();
   }

}

这是我的 ActionFilterAttribute 的示例:

public class CustomAuthorizeAttribute : ActionFilterAttribute
{
   public MyUserTypes UserType { get; set; }

   public override void OnActionExecuting(ActionExecutingContext filterContext)
   {
      myUser user = ((CustomControllerBase)filterContext.Controller).User;

      if(!user.isAuthenticated)
      {
         filterContext.RequestContext.HttpContext.Response.StatusCode = 401;
      }
   }
}

效果很好。

问题如下:我可以要求此属性仅用于我的自定义控制器类型中的操作吗?

【问题讨论】:

  • 您的属性已损坏,因为它不继承自AuthroizeAttribute,因此不能保证在缓存操作时运行。有关使用缓存的解决方案,请参阅 blogs.teamb.com/craigstuntz/2009/09/09/38390
  • 为什么会缓存动作结果?
  • 它会被缓存,因为有人告诉它被缓存。想象一下,有人将 Cache 属性放在父类上,而没有注意到子类型上的损坏属性。使用与 ASP.NET/MVC 缓存不完全不兼容的属性是一个更好的主意。有关选项,请参阅上面的链接。
  • @Craig - 很好。我实际上并没有查看动作过滤器本身。他是对的——如果你编写自己的授权操作过滤器,你真的应该从 AuthorizeAttribute 继承。然后,您可以覆盖 AuthorizeCore() 保护方法。
  • 需要在这里对这个主题进行一些澄清stackoverflow.com/questions/1441799/…

标签: c# asp.net-mvc model-view-controller


【解决方案1】:

基于 cmets 和我系统的限制,我采用了混合方法。基本上,如果请求是通过缓存路由发送的,或者由于任何原因未设置“用户”,则身份验证会以正确的方式失败。

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
  private MyUser User { get; set; }

  public override void OnAuthorization(AuthorizationContext filterContext)
  {
    //Lazy loads the user in the controller.
    User = ((MyControllerBase)filterContext.Controller).User;

    base.OnAuthorization(filterContext);
  }

  protected override bool AuthorizeCore(HttpContextBase httpContext)
  {
    bool isAuthorized = false;
    string retLink = httpContext.Request.Url.AbsolutePath;

    if(User != null)
    {
      isAuthorized = User.IsValidated;
    }

    if (!isAuthorized)
    {
      //If the current request is coming in via an AJAX call,
      //simply return a basic 401 status code, otherwise, 
      //redirect to the login page.
      if (httpContext.Request.IsAjaxRequest())
      {
        httpContext.Response.StatusCode = 401;
      }
      else
      {
        httpContext.Response.Redirect("/login?retlink=" + retLink);
      }
    }

    return isAuthorized;
  }
}

【讨论】:

  • 如果你在任何“isAuthorized=false”的情况下进行重定向,那你为什么不在最后返回true呢?
  • 在IsAjaxRequest流的情况下,用户没有被重定向,所以方法还是需要返回。
  • +1 用于使用 AuthorizeAttribute 而不是 ActionFilterAttribute。解决了具有CustomAuthotize属性的控制器操作即使我们没有登录也会执行的问题,这可能会导致其他问题。
【解决方案2】:

您可以将 ActionFilter 放在类本身上。类中的所有动作都会实现ActionFilter。

[CustomAuthorize]
public class AuthorizedControllerBase : CustomControllerBase
{
}

public class OpenAccessControllerBase : CustomControllerBase
{
}

public class MyRealController : AuthorizedControllerBase 
{
    // GET: /myrealcontroller/index
    public ActionResult Index()
    {
        return View();
    }
}

【讨论】:

  • 我只是在类中定义 ActionFilter 的路线(因此它在其他类中不可用。)很高兴知道该属性可以在控制器中的所有 ActionResults 中定义。
猜你喜欢
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
相关资源
最近更新 更多