对于相同的操作 MVC5,将 ValidateAntiForgeryToken 属性设置为 GET/POST
Set ValidateAntiForgeryToken attribute to GET/POST for same action MVC5
我的问题很直接...
我有一个 Action
接受 HttpGet
和 HttpPost
,但我想在 http 请求为 [=16] 时将 ValidateAntiForgeryToken
属性设置为操作=],不适用于 HttpGet
。
我可以在操作中找到请求是 GET
还是 POST
,但我需要在调用操作之前知道。
[ValidateAntiForgeryToken] // Only for HttpPost
public ActionResult Index() // Allows HttpPost / HttpGet
{
}
是否有可能在不重复操作的情况下实现这一目标?
谢谢
目前框架中还没有内置任何内容可让您执行此操作,但您仍然有一个选择。创建您自己的 ValidateAntiForgeryToken that takes a parameter the http verb/actions 实现,您希望它对其进行验证。最简单的方法是实现接口IAuthorizationFilter
。
您有可能检测到这个 see link:
if (HttpContext.Current.Request.HttpMethod == "POST")
{
// The action is a POST.
}
并且您需要一个方法属性来在 运行 操作之前拦截并采取不同的行为来跳过操作。 ValidateAntiForgeryToken
不是 GET
上的 运行。
您可以有条件地检查请求的 HTTP 方法并自己手动进行验证:
if (Request.Method.ToLower() == "post")
{
System.Web.Helpers.AntiForgery.Validate();
}
首先,这是一个非常糟糕的设计。 MVC 的重点是在控制器中分离方法。如果您希望两种方法具有相同的行为,我建议修改您的控制器以具有一个 GET 和一个 POST,每个方法在控制器的其他地方调用相同的方法。
但是您可以编写一个验证属性来完成您想要的。
基于此 source code,您可以将 Validation 属性中的 OnAuthorization
方法编辑为:
public void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request.HttpMethod;
if (request != "GET")
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
ValidateAction();
}
}
现在检查请求是否为 GET
,在这种情况下它会跳过验证。完整的属性 class 是:
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();
}
}
}
}
我的问题很直接...
我有一个 Action
接受 HttpGet
和 HttpPost
,但我想在 http 请求为 [=16] 时将 ValidateAntiForgeryToken
属性设置为操作=],不适用于 HttpGet
。
我可以在操作中找到请求是 GET
还是 POST
,但我需要在调用操作之前知道。
[ValidateAntiForgeryToken] // Only for HttpPost
public ActionResult Index() // Allows HttpPost / HttpGet
{
}
是否有可能在不重复操作的情况下实现这一目标?
谢谢
目前框架中还没有内置任何内容可让您执行此操作,但您仍然有一个选择。创建您自己的 ValidateAntiForgeryToken that takes a parameter the http verb/actions 实现,您希望它对其进行验证。最简单的方法是实现接口IAuthorizationFilter
。
您有可能检测到这个 see link:
if (HttpContext.Current.Request.HttpMethod == "POST")
{
// The action is a POST.
}
并且您需要一个方法属性来在 运行 操作之前拦截并采取不同的行为来跳过操作。 ValidateAntiForgeryToken
不是 GET
上的 运行。
您可以有条件地检查请求的 HTTP 方法并自己手动进行验证:
if (Request.Method.ToLower() == "post")
{
System.Web.Helpers.AntiForgery.Validate();
}
首先,这是一个非常糟糕的设计。 MVC 的重点是在控制器中分离方法。如果您希望两种方法具有相同的行为,我建议修改您的控制器以具有一个 GET 和一个 POST,每个方法在控制器的其他地方调用相同的方法。
但是您可以编写一个验证属性来完成您想要的。
基于此 source code,您可以将 Validation 属性中的 OnAuthorization
方法编辑为:
public void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request.HttpMethod;
if (request != "GET")
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
ValidateAction();
}
}
现在检查请求是否为 GET
,在这种情况下它会跳过验证。完整的属性 class 是:
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();
}
}
}
}