asp.net-mvc - 指定实现时带有接口类的 WebAPI 模型 [ModelBinder]
问题描述
是否可以将要内联使用的实现传递给 ModelBinder?
给定以下定义:
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; }
}
}
鉴于asp.net mvc核心中的这条路线:
public ActionResult InterfaceWithInlineImplementation([ModelBinder(typeof(SomeBinder))]ISomeInterface SomeInterface)
{
//Return actionresult
}
我不希望每个实现都使用不同的 ModelBinder 类,而是希望每个路由都指定哪个内联实现。
所以像:
[UseImplementation(SomeInterfaceImplementation_One)]
public ActionResult InterfaceWithInlineImplementation([ModelBinder(typeof(SomeBinder))]ISomeInterface SomeInterface)
{
}
或者:
public ActionResult InterfaceWithInlineImplementation([ModelBinder(typeof(SomeBinder), ConcreteType = SomeInterfaceImplementation_Two )]ISomeInterface SomeInterface)
{
}
这样, SomeBinder 类可以访问 SomeBinder 的 BindModelAsync 方法中请求的实现:IModelBinder 类。
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;
}
解决方案
使用泛型。
public class SomeBinder<TConcreteType> : IModelBinder
{
}
然后你的签名变成
public ActionResult InterfaceWithInlineImplementation(
[ModelBinder(typeof(SomeBinder<SomeInterfaceImpelemtation_One>))]ISomeInterface SomeInterface)
那么反序列化就是:
JsonConvert.DeserializeObject<TConcreteType>(json)
但是,根据您的最后评论,听起来您只需要防止过度发布而不是这种复杂的模型绑定。
因此,假设客户端知道服务器实现具有安全方法并尝试匹配签名,例如希望一切都被反序列化。它对您的期望很明确。而且您明确地只期望合同定义,仅此而已。
摘抄:
质量分配通常在模型绑定期间作为 MVC 的一部分发生。一个简单的例子是您的网站上有一个表单,您正在其中编辑一些数据。您的模型上还有一些属性作为表单的一部分不可编辑,而是用于控制表单的显示,或者根本不使用。
public class UserModel
{
public string Name { get; set; }
public bool IsAdmin { get; set; }
}
所以这里的想法是您只将单个输入标记呈现给标记,但您将其发布到使用与用于呈现相同的模型的方法中:
[HttpPost]
public IActionResult Vulnerable(UserModel model)
{
return View("Index", model);
}
但是,通过一些简单的 HTML 操作,或者通过使用 Postman/Fiddler,恶意用户可以将 IsAdmin 字段设置为 true。模型绑定器将尽职尽责地绑定该值,而您刚刚成为批量分配/过度发布的受害者:
那么如何防止这种攻击呢?幸运的是,有很多不同的方法,它们通常与您可以在以前版本的 ASP.NET 中使用的方法相同。我将在这里介绍您的一些选择。
推荐阅读
- android - 我想在软键盘上方创建一个视图
- amazon-web-services - 如何配置我的 EC2 实例运行 DPDK 以过滤弹性 IP 和另一个 ec2 实例之间的流量?
- python - Extracting name and number from a string
- ruby - 在 Firestore 中写入需要太多时间
- java - 如何使用 log4j 动态设置日志文件名,但在发出数据库请求之后?
- java - 为什么通知没有显示在 API 28 中?
- c - 如何将 VL53L0X 标头包含到我的 STM32L 项目中
- python - pythonscript将图片保存到文件时如何在网络服务器上显示图片?
- visual-studio-code - VSCode Jest 因 SystaxError 失败:意外的令牌 =
- python - 将(冻结的)Tensorflow 模型加载到内存中时出错