.NET API 接口数据传输加密最佳实践( 三 )

IApiEncrypt 接口标签的才会正常进行解析绑定 。
剩下的就是在 ConfigureService 中添加进去即可:
services.AddControllers(options => { ... options.ModelBinderProviders.Insert(0, new SecurityTransportModelBinderProvider());})这样实现过后,我们就能像使用 FromBody 那样就能按需调用即可:
[HttpPost("security")]public async Task<ResultDto> DemoDecrypt([ModelBinder(typeof(SecurityTransportModelBinder))] OriginBusinessRequest request){//激活结果 ...return await Task.FromResult(WriteSafeData(data, publicKey));}如果是默认处理加解密也是可以的,直接在对应的请求实体类打上 IApiEncrypt 标签就会自动执行模型绑定
public class UserUpdateRequest: IApiEncrypt { public int UserId { get; set; } public string Phone { get; set; } public string Address { get; set; } ...}这种方案其实也还是有缺点的 , 从刚刚的使用来看就知道,模型绑定无法解决返回自动加密处理 。所以我们不得不在每个接口处写下如 WriteSafeData(data, publicKey) 这种显式加密的代码 。
优化的方式也很简单,其实我们可以通过过滤器可以解决,这也是为什么我要加 IApiEncrypt 的原因,因为有了这个就能确定知道这是一个安全传输的请求,进而进行特殊处理 。

注意,这不是 .NET Core 独有的特性,.Net Framework 也有模型绑定器
总结针对接口级传输加密这个需求,我们总共讨论了四种实现方式 。其实各有各的好处和缺点 。
硬编码方式适合只有特定需求的场景下是适合这种方案的 。但是一旦这种需求成为一种规范或普遍场景时,这个方法就不合适了
统一入口适合制定了一种接口规范,所有加密的请求都走这一个接口 。然后通过路由解析调度到不同的控制器 。其实我讲了我司在 .NET Framework 下采取的一种方案 , 好处时实现简单,做到了代码复用,对业务代码进行了解耦 。但缺点是用了反射成为了性能消耗点,并且当业务越来越多就会产生代码爆炸,成为了维护灾难 。
而中间件或 IHttpModule 方式就很好的解决这了这点 。但同样也不是使用所有场景,如对新增的不需要加密的接口要进行过滤处理等 。
最后介绍了模型绑定这种方式,技能很方便的满足大多数场景 , 也满足个别列外的需求 。但同样也有缺点,就是无法针对接口响应体进行自动加密处理,所谓好事做到底,送佛送到西 , 这事只能算是做到一半吧 。
其实我还想到了一种类似 Aop 的方案,那就是实现一个路由过滤器的功能,当请求进来,通过路由处理程序对请求体进行解密,然后重写请求流 。然后调度到对应的原始路由,最后在响应的时候再加密重写一次 。不过查阅了一番资料,并没有收获 。
参考资料
  • https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.imodelbinderprovider?view=aspnetcore-7.0
  • https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/write?view=aspnetcore-6.0
  • https://www.stevejgordon.co.uk/html-encode-string-aspnet-core-model-binding
【.NET API 接口数据传输加密最佳实践】

推荐阅读