我想AntiForgeryTokens
在每个 HttpPost 操作上使用一个 ActionFilter,该控制器位于一个名为ControllerBase
该控制器的控制器中,每个其他控制器都继承自该控制器。
我想通过创建一个继承自它的 ActionFilter 来做到这一点,ValidateAntiForgeryToken
它接受一个参数来告诉它要将自身应用于哪些 HTTP 动词。然后我想应用该过滤器 ControllerBase
以确保AntiForgeryToken
检查整个站点上的每个 POST 操作。
我正在考虑使用这个解决方案,但是
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;
}
}
}