web-dev-qa-db-ja.com

ASP.NET MVCカスタムmodelbinderの使用時に、潜在的に危険なRequest.Form値がクライアントから検出されました

ここでエラーを取得します:

ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");

選択した値のみを許可するにはどうすればよいですか?つまり.

[ValidateInput(false)]
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");
    ValueProviderResult value2 = bindingContext.ValueProvider.GetValue("ConfirmationMessage2");
}
90
D-W

いくつかのオプションがあります。

モデルでは、HTMLを許可する必要がある各プロパティにこの属性を追加します-best choice

using System.Web.Mvc;

[AllowHtml]
public string SomeProperty { get; set; }

コントローラーアクションでこの属性を追加して、すべてのHTML

[ValidateInput(false)]
public ActionResult SomeAction(MyViewModel myViewModel)

Web.configのブルートフォース-絶対に推奨されません

Web.configファイルのタグ内で、属性requestValidationMode = "2.0"を持つhttpRuntime要素を挿入します。また、pages要素にvalidateRequest = "false"属性を追加します。

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>

詳細: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

上記は、デフォルトのモデルバインダーの使用に対して機能します。

カスタムModelBinder

上記のコードのbindingContext.ValueProvider.GetValue()の呼び出しは、属性に関係なく、常にデータを検証するようです。 ASP.NET MVCソースを掘り下げると、DefaultModelBinderが最初に要求の検証が必要かどうかを確認し、検証が必要かどうかを示すパラメーターを指定してbindingContext.UnvalidatedValueProvider.GetValue()メソッドを呼び出していることがわかります。

残念なことに、無知な開発者を危険なことから保護するために封印されたプライベートなものであるため、フレームワークコードは使用できませんが、AllowHtmlおよびValidateInput属性を尊重する動作するカスタムモデルバインダーを作成することはそれほど難しくありません。

public class MyModelBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // First check if request validation is required
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && bindingContext.ModelMetadata.RequestValidationEnabled;

        // Get value
        var valueProviderResult = bindingContext.GetValueFromValueProvider(shouldPerformRequestValidation);
        if (valueProviderResult != null)
        {
            var theValue = valueProviderResult.AttemptedValue;

            // etc...
        }
    }
}

他の必要な部分は、未検証の値を取得する方法です。この例では、ModelBindingContextクラスの拡張メソッドを使用します。

public static class ExtensionHelpers
{
    public static ValueProviderResult GetValueFromValueProvider(this ModelBindingContext bindingContext, bool performRequestValidation)
    {
        var unvalidatedValueProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;
        return (unvalidatedValueProvider != null)
          ? unvalidatedValueProvider.GetValue(bindingContext.ModelName, !performRequestValidation)
          : bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
    }
}

詳細については http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/

209
ericdc

試してください:

HttpRequestBase request = controllerContext.HttpContext.Request;
string re = request.Unvalidated.Form.Get("ConfirmationMessage")
29
D-W

@ D-Wからの回答を拡張して、私の編集コントローラーで、フォーム値を反復処理する際に、Request.Params.AllKeysのすべてのインスタンスをRequest.Unvalidated.Form.AllKeysに、Request[key]のすべてのインスタンスをRequest.Unvalidated.Form[key]に置き換える必要がありました。

これが私にとって有効な唯一のソリューションでした。

2
Mike Godin