简体   繁体   English

指定实现的同时具有接口类的WebAPI模型[ModelBinder]

[英]WebAPI Model [ModelBinder] with interface class while specifying implementation

Is it possible to pass into the ModelBinder which implementation you want to use inline? 是否可以将要内联使用的实现传递给ModelBinder?

Given the following definitions: 给出以下定义:

public interface ISomeInterface
{
    string MyString{get;set;}
}

public class SomeInterfaceImplementation_One : ISomeInterface
{
    private string _MyString;

    public string MyString
    {
       get {return "This is implementation One " + _MyString ; }
       set { _MyString = value;  }
    }
}

public class SomeInterfaceImplementation_Two : ISomeInterface
{
    private string _MyString;

    public string MyString
    {
       get {return "This is implementation Two" + _MyString ; }
       set { _MyString = value;  }
    }
}

Given this route in asp.net mvc core: 在asp.net mvc核心中给出以下路由:

public ActionResult InterfaceWithInlineImplementation([ModelBinder(typeof(SomeBinder))]ISomeInterface SomeInterface)
{
       //Return actionresult
}

I do not want a different ModelBinder class for each implementation rather I would like each route to specify which implementation inline. 我不想为每个实现使用不同的ModelBinder类,而是希望每个路由指定内联哪个实现。

So something like: 所以像这样:

[UseImplementation(SomeInterfaceImplementation_One)]
public ActionResult InterfaceWithInlineImplementation([ModelBinder(typeof(SomeBinder))]ISomeInterface SomeInterface)
{

}

Or: 要么:

 public ActionResult InterfaceWithInlineImplementation([ModelBinder(typeof(SomeBinder), ConcreteType = SomeInterfaceImplementation_Two )]ISomeInterface SomeInterface)
    {

    }

This way the SomeBinder class can access which implementation is being requested in the BindModelAsync method of SomeBinder : IModelBinder class. 这样,SomeBinder类可以访问SomeBinder:IModelBinder类的BindModelAsync方法中请求的实现。

public class SomeBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder
    {

        public Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
                throw new ArgumentNullException(nameof(bindingContext));

            string valueFromBody = string.Empty;

            using (var sr = new StreamReader(bindingContext.HttpContext.Request.Body))
            {
                valueFromBody = sr.ReadToEnd();
            }

            if (string.IsNullOrEmpty(valueFromBody))
            {
                return Task.CompletedTask;
            }

            var settings = new JsonSerializerSettings()
            {
                ContractResolver = new InterfaceContractResolver(), // Need requested implementation from InterfaceWithInlineImplementation() method

            }; 

            var obj = JsonConvert.DeserializeObject(valueFromBody, [**Need Requested Implementation from Method**], settings);
            bindingContext.Model = obj;


            bindingContext.Result = ModelBindingResult.Success(obj);


            return Task.CompletedTask;
        }

Use generics. 使用泛型。

public class SomeBinder<TConcreteType> : IModelBinder
{
}

Then your signature becomes 然后你的签名变成

public ActionResult InterfaceWithInlineImplementation(
  [ModelBinder(typeof(SomeBinder<SomeInterfaceImpelemtation_One>))]ISomeInterface SomeInterface)

Then deserialization is: 然后反序列化是:

JsonConvert.DeserializeObject<TConcreteType>(json)

However based on your last comment it sounds like you just need to Prevent overposting instead of this convoluted model binding. 但是,根据您的最新评论,听起来您只需要防止过度发布,而不是这种复杂的模型绑定即可。

So lets say the client knows that the server implementation has security methods and tries to match the signature hoping everything get deseriazled for example. 因此,可以说客户知道服务器实现具有安全性方法,并尝试匹配签名,以希望例如一切反序列化。 Its being explicit as to what you're expecting. 它对您的期望是明确的。 And you're explicitly expecting only the contract definition and nothing more. 您显然只期望合同定义,仅此而已。

Excerpt: 摘抄:

Mass assignment typically occurs during model binding as part of MVC. 质量分配通常在模型绑定期间作为MVC的一部分发生。 A simple example would be where you have a form on your website in which you are editing some data. 一个简单的例子是您在网站上有一个正在编辑一些数据的表单。 You also have some properties on your model which are not editable as part of the form, but instead are used to control the display of the form, or may not be used at all. 您的模型上还具有一些属性,这些属性不能作为表单的一部分进行编辑,而是用于控制表单的显示,或者可能根本不使用。

public class UserModel
{
  public string Name { get; set; }
  public bool IsAdmin { get; set; }
}

So the idea here is that you only render a single input tag to the markup, but you post this to a method that uses the same model as you used for rendering: 因此,这里的想法是,您只向标记呈现一个输入标签,但是将其发布到使用与呈现相同模型的方法中:

[HttpPost]
public IActionResult Vulnerable(UserModel model)
{
    return View("Index", model);
}

However, with a simple bit of HTML manipulation, or by using Postman/Fiddler , a malicious user can set the IsAdmin field to true. 但是,通过简单的HTML操作或使用Postman / Fiddler,恶意用户可以将IsAdmin字段设置为true。 The model binder will dutifully bind the value, and you have just fallen victim to mass assignment/over posting: 模型绑定器将忠实地绑定值,而您刚刚成为批量分配/过帐的牺牲品:

So how can you prevent this attack? 那么如何防止这种攻击呢? Luckily there's a whole host of different ways, and they are generally the same as the approaches you could use in the previous version of ASP.NET. 幸运的是,有很多不同的方法,它们通常与您在以前版本的ASP.NET中可以使用的方法相同。 I'll run through a number of your options here. 我将在这里介绍您的许多选择。

Continue to article... 继续文章...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM