有沒有什麼辦法可以集中執行每個操作方法都必須具有「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