将 ValidateAntiForgeryToken 属性设置为 GET/POST 以获得相同的操作 MVC5
本文关键字:MVC5 操作 POST 属性 ValidateAntiForgeryToken 设置 GET | 更新日期: 2023-09-27 18:32:23
我的问题很简单...
我有一个接受HttpGet
和HttpPost
的Action
,但我想在 http 请求POST
时将ValidateAntiForgeryToken
属性设置为操作,而不是HttpGet
。
我可以找到请求是在操作中GET
还是POST
,但我需要在调用操作之前知道。
[ValidateAntiForgeryToken] // Only for HttpPost
public ActionResult Index() // Allows HttpPost / HttpGet
{
}
是否有可能在不重复操作的情况下实现这一目标?
谢谢
您可以有条件地检查请求的 HTTP 方法并自己手动执行验证:
if (Request.Method.ToLower() == "post")
{
System.Web.Helpers.AntiForgery.Validate();
}
首先,这是一个非常糟糕的设计。MVC 的要点是分离控制器中的方法。如果您希望两个方法具有相同的行为,我建议修改您的控制器以具有 GET 和 POST,每个方法在控制器中的其他地方调用相同的方法。
但是,您可以编写验证属性来完成所需的操作。
基于此源代码,可以将"验证"属性中的OnAuthorization
方法编辑为:
public void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request.HttpMethod;
if (request != "GET")
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
ValidateAction();
}
}
它现在检查请求是否GET
在这种情况下,它会跳过验证。完整的属性类是:
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Web.Helpers;
namespace System.Web.Mvc
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ValidateAntiForgeryTokenAttribute2 : FilterAttribute, IAuthorizationFilter
{
private string _salt;
public ValidateAntiForgeryTokenAttribute2()
: this(AntiForgery.Validate)
{
}
internal ValidateAntiForgeryTokenAttribute2(Action validateAction)
{
Debug.Assert(validateAction != null);
ValidateAction = validateAction;
}
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "AdditionalDataProvider", Justification = "API name.")]
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "AntiForgeryConfig", Justification = "API name.")]
[Obsolete("The 'Salt' property is deprecated. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property.", error: true)]
[EditorBrowsable(EditorBrowsableState.Never)]
public string Salt
{
get { return _salt; }
set
{
if (!String.IsNullOrEmpty(value))
{
throw new NotSupportedException("The 'Salt' property is deprecated. To specify custom data to be embedded within the token, use the static AntiForgeryConfig.AdditionalDataProvider property.");
}
_salt = value;
}
}
internal Action ValidateAction { get; private set; }
public void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request.HttpMethod;
if (request != "GET")
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
ValidateAction();
}
}
}
}
框架中目前没有内置任何允许您执行此操作的内容,但您仍然有一个选择。创建您自己的 ValidateAntiForgeryToken 实现,该实现采用您希望它验证的 http 动词/操作的参数。最简单的方法是实现接口IAuthorizationFilter
。
您可以检测到此链接:
if (HttpContext.Current.Request.HttpMethod == "POST")
{
// The action is a POST.
}
并且您需要一个方法属性来在运行操作之前进行拦截,并采取不同的行为来跳过操作。该ValidateAntiForgeryToken
不会在HTTP GET中使用MVC3的AntiForgeryToken GET
上运行,以避免Javascript CSRF漏洞。