Как мне написать ActionFilter, который гарантирует использование AntiForgeryTokens для каждой операции Post?

Я хочу использовать AntiForgeryTokensдля каждого действия HttpPost, используя ActionFilter, который находится в контроллере с именем ControllerBase, от которого наследуется каждый другой контроллер.

Я хочу сделать это, создав 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);
        }

        /// 
        /// 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
        /// 
        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;
        }
    }
}

8
задан Ecnalyr 2 August 2012 в 16:06
поделиться