有没有什么办法可以集中执行每个操作方法都必须具有“ValidateAntiForgeryToken”属性?我认为这必须通过扩展一个“路由”类来完成。确保每个控制器方法都具有ValidateAntiForgeryToken属性?
编辑:或者也许在应用程序启动时做一些反思?
有没有什么办法可以集中执行每个操作方法都必须具有“ValidateAntiForgeryToken”属性?我认为这必须通过扩展一个“路由”类来完成。确保每个控制器方法都具有ValidateAntiForgeryToken属性?
编辑:或者也许在应用程序启动时做一些反思?
是的。你可以通过创建你自己的BaseController来继承Mvc控制器,并重载OnAuthorization()。你要强制执行之前,以确保它是一个POST事件:
public abstract class MyBaseController : Controller
{
protected override void OnAuthorization(AuthorizationContext filterContext)
{
//enforce anti-forgery stuff for HttpVerbs.Post
if (String.Compare(filterContext.HttpContext.Request.HttpMethod,
System.Net.WebRequestMethods.Http.Post, true) == 0)
{
var forgery = new ValidateAntiForgeryTokenAttribute();
forgery.OnAuthorization(filterContext);
}
base.OnAuthorization(filterContext);
}
}
一旦你的,确保所有控制器,从这个MyBaseController(或者无论你怎么称呼它)继承。或者,如果您喜欢使用相同的代码,则可以在每个控制器上执行此操作。
听起来像你试图阻止“哎呀我忘了设置”的错误。如果是这样,我认为最好的地方是使用自定义的ControllerActionInvoker。
基本上你想要做的是,即使找到一个动作没有防伪标记停止MVC:
public class MustHaveAntiForgeryActionInvoker : ControllerActionInvoker
{
protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
var foundAction = base.FindAction(controllerContext, controllerDescriptor, actionName);
if(foundAction.GetCustomAttributes(typeof(ValidateAntiForgeryTokenAttribute), true).Length == 0)
throw new InvalidOperationException("Can't find a secure action method to execute");
return foundAction;
}
}
然后在你的控制器,最好是你的基本控制器:
ActionInvoker = new MustHaveAntiForgeryActionInvoker();
只是想添加自定义控制器基类往往会变得“厚”,而且它始终是最好的实践,以便使用MVC的卓越可扩展性来抓住它们所属的特性。
这里是大多数的MVC的扩展点有很好的指导: http://codeclimber.net.nz/archive/2009/04/08/13-asp.net-mvc-extensibility-points-you-have-to-know.aspx
好吧,我刚刚升级了一个项目,MVC V2.0这里,和eduncan911的解决方案不工作了,如果你使用的AuthorizeAttribute
你的控制器动作。找出原因有点难。
因此,故事中的罪魁祸首是MVC团队在RequestVerificationToken
的值中添加了使用ViewContext.HttpContext.User.Identity.Name
属性。
在基本控制器中重写的OnAuthorization
在控制器动作的任何过滤器之前执行。所以,问题在于Authorize属性尚未被调用,因此未设置ViewContext.HttpContext.User
。所以UserName是String.Empty,而用于验证的AntiForgeryToken包含真正的用户名= fail。
我们使用此代码现在解决了这个问题:
public abstract class MyBaseController : Controller
{
protected override void OnAuthorization(AuthorizationContext filterContext)
{
//enforce anti-forgery stuff for HttpVerbs.Post
if (String.Compare(filterContext.HttpContext.Request.HttpMethod, "post", true) == 0)
{
var authorize = new AuthorizeAttribute();
authorize.OnAuthorization(filterContext);
if (filterContext.Result != null) // Short circuit validation
return;
var forgery = new ValidateAntiForgeryTokenAttribute();
forgery.OnAuthorization(filterContext);
}
base.OnAuthorization(filterContext);
}
}
到MVC代码库的一些参考文献:
ControllerActionInvoker#InvokeAuthorizationFilters()
线283相同短路。 AntiForgeryData#GetUsername()
第98行。新功能。
我继续前进,并给雅上升(+3,哇!)。但是,我在3.5框架中使用了VS2010 RTM的MVC 2.0 RTM(这是一个Azure项目,所以我现在必须保持3.5)。我发布的防伪解决方案仍然有效。我想知道这个问题是你使用MVC 2.0 RC2还是一样? – eduncan911 2010-04-26 01:08:22
这个怎么样?
[ValidateAntiForgeryToken]
public class MyBaseController : Controller
{
}
此解决方案接缝不适用于MVC2。它对MVC1来说工作得很好,但是一旦我们升级到v2,它就停止工作。试图找到一个解决方案。 – 2010-03-29 12:14:03
感谢您将此引入我的注意。我也会考虑一下。 – eduncan911 2010-03-29 14:00:37
我至少发现_a_解决方案,而不是最好的解决方案。请参阅下面的答案。评论框不是很好,代码格式=) – 2010-03-29 14:55:15