对于相同的操作 MVC5,将 ValidateAntiForgeryToken 属性设置为 GET/POST

Set ValidateAntiForgeryToken attribute to GET/POST for same action MVC5

我的问题很直接...

我有一个 Action 接受 HttpGetHttpPost,但我想在 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();
        }
    }
}

}