8

他のすべてのコントローラーが継承するAntiForgeryTokensという名前のコントローラーにある ActionFilter を使用して、すべての HttpPost アクションで使用したいと考えています。ControllerBase

これを行うには、継承する ActionFilter を作成して、ValidateAntiForgeryTokenどの HTTP 動詞に適用するかを伝える引数を取ります。次に、そのフィルターを適用し て、サイト全体ですべての POST 操作がチェックさControllerBaseれるようにします。AntiForgeryToken

私はこのソリューションの使用を検討していましたが、

  • AuthorizationContext Constructor (ControllerContext)は廃止されたコンストラクターが含まれており、推奨される を使用してコードを再構築する方法がわかりませんAuthorizationContext(ControllerContext controllerContext, ActionDescriptor actionDescriptor)

  • 次のエラーが発生するため、デフォルトで AntiForgeryToken を使用していないようですA required anti-forgery token was not supplied or was invalid。すべての投稿アクションの後。

[HttpPost]現在の廃止されていない基準を満たし、すべての動詞で偽造防止トークンを適切に使用するには、ActionFilter をどのように書き直す必要がありますか?

すべてのフォームに自分で偽造防止トークンを含める必要がありますか (そうすると思います)? (自動的に生成されるのではなく、笑わないでください、興味があります) 更新:コメントで指摘されたように。はい、これはすべてのフォームで行う必要があります。

参考までに、私の 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);
        }

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

2 に答える 2

7

私は次のアプローチを使用しました:

public class SkipCSRFCheckAttribute : Attribute
{
}

public class AntiForgeryTokenFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (IsHttpPostRequest(filterContext) && !SkipCsrfCheck(filterContext))
            AntiForgery.Validate();
    }

    private static bool IsHttpPostRequest(AuthorizationContext filterContext)
    {
        return filterContext.RequestContext.HttpContext.Request.HttpMethod == HttpMethod.Post.ToString();
    }

    private static bool SkipCsrfCheck(AuthorizationContext filterContext)
    {
        return filterContext.ActionDescriptor.GetCustomAttributes(typeof (SkipCSRFCheck), false).Any();
    }
}

これにより、SkipCSRFCheck 属性を使用してケースバイケースで無効にし、Application_Start でグローバル フィルターとして登録することができます。

GlobalFilters.Filters.Add(新しい AntiForgeryTokenFilter());

于 2014-02-22T13:33:40.340 に答える
1

AuthorizationContextインスタンス化したり、メソッドを呼び出したりする必要はありませんOnAuthorization。単純に:

if (ShouldValidateAntiForgeryTokenManually(filterContext))
{
    AntiForgery.Validate(filterContext.HttpContext, null);
}
于 2012-08-03T06:30:54.340 に答える