他のすべてのコントローラーが継承するAntiForgeryTokens
という名前のコントローラーにある ActionFilter を使用して、すべての HttpPost アクションで使用したいと考えています。ControllerBase
これを行うには、継承する ActionFilter を作成して、ValidateAntiForgeryToken
どの HTTP 動詞に適用するかを伝える引数を取ります。次に、そのフィルターを適用し て、サイト全体ですべての POST 操作がチェックさControllerBase
れるようにします。AntiForgeryToken
私はこのソリューションの使用を検討していましたが、
AuthorizationContext Constructor (ControllerContext)
は廃止されたコンストラクターが含まれており、推奨される を使用してコードを再構築する方法がわかりませんAuthorizationContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
。次のエラーが発生するため、デフォルトで AntiForgeryToken を使用していないようですA required anti-forgery token was not supplied or was invalid
。すべての投稿アクションの後。
[HttpPost]
現在の廃止されていない基準を満たし、すべての動詞で偽造防止トークンを適切に使用するには、ActionFilter をどのように書き直す必要がありますか?
すべてのフォームに自分で偽造防止トークンを含める必要がありますか (そうすると思います)? (自動的に生成されるのではなく、笑わないでください、興味があります) 更新:コメントで指摘されたように。はい、これはすべてのフォームで行う必要があります。
参考までに、私の ControllerBase のコードを次に示します。
[UseAntiForgeryTokenOnPostByDefault]
public class ControllerBase : Controller
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class BypassAntiForgeryTokenAttribute : ActionFilterAttribute
{
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class UseAntiForgeryTokenOnPostByDefault : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (ShouldValidateAntiForgeryTokenManually(filterContext))
{
var authorizationContext = new AuthorizationContext(filterContext.Controller.ControllerContext);
//Use the authorization of the anti forgery token,
//which can't be inhereted from because it is sealed
new ValidateAntiForgeryTokenAttribute().OnAuthorization(authorizationContext);
}
base.OnActionExecuting(filterContext);
}
/// <summary>
/// We should validate the anti forgery token manually if the following criteria are met:
/// 1. The http method must be POST
/// 2. There is not an existing [ValidateAntiForgeryToken] attribute on the action
/// 3. There is no [BypassAntiForgeryToken] attribute on the action
/// </summary>
private static bool ShouldValidateAntiForgeryTokenManually(ActionExecutingContext filterContext)
{
var httpMethod = filterContext.HttpContext.Request.HttpMethod;
//1. The http method must be POST
if (httpMethod != "POST") return false;
// 2. There is not an existing anti forgery token attribute on the action
var antiForgeryAttributes =
filterContext.ActionDescriptor.GetCustomAttributes(typeof (ValidateAntiForgeryTokenAttribute), false);
if (antiForgeryAttributes.Length > 0) return false;
// 3. There is no [BypassAntiForgeryToken] attribute on the action
var ignoreAntiForgeryAttributes =
filterContext.ActionDescriptor.GetCustomAttributes(typeof (BypassAntiForgeryTokenAttribute), false);
if (ignoreAntiForgeryAttributes.Length > 0) return false;
return true;
}
}
}