Ecn*_*lyr 8 asp.net-mvc http-verbs action-filter antiforgerytoken asp.net-mvc-3
我希望AntiForgeryTokens在每个HttpPost Action上使用ActionFilter,该ActionFilter位于ControllerBase每个其他控制器继承的控制器中.
我想通过创建一个ActionFilter来实现这一点,该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每次发布后操作.
我应该如何重写ActionFilter以满足当前的非过时标准并在每个[HttpPost]动词上正确使用防伪标记?
我是否必须在每种形式中都包含一个防伪标记(我在想)?(而不是自动生成 - 不要笑,我很好奇) 更新:正如评论中指出的那样; 是的,这必须在每个表格中完成.
以下是我的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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我使用了以下方法:
public class SkipCSRFCheckAttribute : Attribute
{
}
public class AntiForgeryTokenFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (IsHttpPostRequest(filterContext) && !SkipCsrfCheck(filterContext))
AntiForgery.Validate();
}
private static bool IsHttpPostRequest(AuthorizationContext filterContext)
{
return filterContext.RequestContext.HttpContext.Request.HttpMethod == HttpMethod.Post.ToString();
}
private static bool SkipCsrfCheck(AuthorizationContext filterContext)
{
return filterContext.ActionDescriptor.GetCustomAttributes(typeof (SkipCSRFCheck), false).Any();
}
}
Run Code Online (Sandbox Code Playgroud)
这使我们能够使用SkipCSRFCheck属性逐个禁用它,然后在Application_Start中将其注册为全局过滤器:
GlobalFilters.Filters.Add(new AntiForgeryTokenFilter());
您不需要实例化任何AuthorizationContext或调用该OnAuthorization方法,只需:
if (ShouldValidateAntiForgeryTokenManually(filterContext))
{
AntiForgery.Validate(filterContext.HttpContext, null);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4045 次 |
| 最近记录: |