我的问题很直接......
我有Action
同时接受HttpGet
和HttpPost
,但我想在http请求为ValidateAntiForgeryToken
时将POST
属性设置为操作,不适用于HttpGet
。
我可以在操作中找到请求是GET
还是POST
,但我需要在调用操作之前知道。
[ValidateAntiForgeryToken] // Only for HttpPost
public ActionResult Index() // Allows HttpPost / HttpGet
{
}
有没有可能在没有重复行动的情况下实现这一目标?
谢谢
答案 0 :(得分:6)
您可以有条件地检查请求的HTTP方法并自行手动执行验证:
if (Request.Method.ToLower() == "post")
{
System.Web.Helpers.AntiForgery.Validate();
}
答案 1 :(得分:2)
首先,这是一个非常糟糕的设计。 MVC的要点是分离控制器中的方法。如果你想让两种方法具有相同的行为,我建议你修改你的控制器,使其具有一个GET和一个POST,每个都在控制器的其他地方调用相同的方法。
但是你可以写一个Validation属性来完成你想要的东西。
根据此source code,您可以将验证属性中的OnAuthorization
方法编辑为:
public void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request.HttpMethod;
if (request != "GET")
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
ValidateAction();
}
}
现在检查请求是否为GET
,在这种情况下它会跳过验证。完整的Attribute类是:
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();
}
}
}
}
答案 2 :(得分:1)
框架中已经没有任何内置功能可以让您执行此操作但仍有一个选项。创建自己的ValidateAntiForgeryToken实现,其中包含您希望其验证的http verb/actions参数。最简单的方法是实现接口IAuthorizationFilter
。
答案 3 :(得分:1)
您可以检测到此see link:
if (HttpContext.Current.Request.HttpMethod == "POST")
{
// The action is a POST.
}
并且您需要在运行操作之前拦截方法属性,并采取不同的行为来跳过操作。 ValidateAntiForgeryToken
未在GET
Using MVC3's AntiForgeryToken in HTTP GET to avoid Javascript CSRF vulnerability上投放。