中间件其实我们熟悉了 .NETCore 下的 Middleware机制,我们会很容易的在 .NETCore 下实现如标题的这种需求:
// .NET Core 版本public class SecuriryTransportMiddleware {private readonly RequestDelegate _next;public RequestCultureMiddleware(RequestDelegate next){_next = next;}public async Task InvokeAsync(HttpContext context){// request handlevar encryptedBody = context.Request.Body;var encryptedContent = new StreamReader(encryptedBody).ReadToEnd();var decryptedBody = RsaHelper.Decrypt(privateKey, encryptedContent);var originBody = JsonHelper.Deserialize<object>(decryptedBody);var json = JsonHelper.Serialize(dataSource);var requestContent = new StringContent(json, Encoding.UTF8, "application/json");stream = await requestContent.ReadAsStreamAsync();context.Request.Body = stream;await _next(context);// response handlevar originContent = new StreamReader(context.Response.Body).ReadToEnd();var encryptedBody = RsaHelper.Encrypt(privateKey, originContent);var responseContent = new StringContent(json, Encoding.UTF8, "application/json");context.Response.Body = await responseContent.ReadAsStreamAsync();// 或者直接// await context.Response.WriteAsync(encryptedBody);}}为了方便描述,以上代码我省略了必要的校验和异常错误处理
这样有什么好处呢?一个最明显的好处就是解耦了加解密与真正业务需求 。对真正的业务代码几乎没有侵略性 。其实我认为业务开发能做到这里其实就差不多了,还有其它需求都可以基于这个中间件进行拓展开发 。
那么在 .NET Framwork 没有中间件怎么办呢?
其实在 .NET Framwork 框架下 IHttpModule 能和中间件一样能做到这点:
public class SecurityTransportHttpModule : IHttpModule { ... public void Init(HttpApplication context) {...context.BeginRequest += ContextBeginRequest;context.PostRequestHandlerExecute += ContextPostRequestHandlerExecute; } private void ContextBeginRequest(object sender, EventArgs e) {HttpContext context = ((HttpApplication)sender).Context;var encryptedBody = context.Request.Body;...context.Request.Body = stream; } private void ContextPostRequestHandlerExecute(object sender, EventArgs e){HttpContext context = ((HttpApplication)sender).Context;...context.Response.Write(encryptedBody)}}【.NET API 接口数据传输加密最佳实践】为什么之前提到这种方案就“差不多”了呢,实际上上面这种方式在某些场景下会显得比较“累赘” 。因为无论通过中间件和还是 IHttpModule 都会导致所有请求都会经过它,相当于增加了一个过滤器,如果这时候我要新增一个上传文件接口,那必然也会经过这个处理程序 。说的更直接一点,如果碰到那些少数不需要加解密的接口请求那要怎么办呢?
其实上面可以进行拓展处理,比如对特定的请求进行过滤:
if(context.Request.Path.Contains("upload")) { return;}
注意上述代码只是做个 demo 展示,真正还是需要通过如当类似于这种需求开始变多以后(吐槽:谁知道业务是怎么发展的呢?)原来的中间件的“任务量”开始变得厚重了起来 。到时候也会变得难以维护和阅读 。context.GetRouterData()获取路由数据进行精准比对 。
这个时候就是我目前较为满意的解决方案登场了,它就是模型绑定 ModelBinding 。
模型绑定回到需求的开端,不难发现,我们其实要是如何将前端加密后的请求体绑定到我们编写的接口方法中 。这里面的过程很复杂,需要解析前端发起的请求,解密之后还要反序列化成目标接口需要的方法参数 。而这个过程还要伴随着参数校验,如这个请求是否符合加密格式 。而这个过程的一切都是模型绑定要解决的事 。我们以 NETCore 版本为例子,讲一下大概的流程;
经验总结扩展阅读
- 重新整理 .net core 实践篇 ———— linux 上线篇 [外篇]
- node.js:《接口实现文件的上传和下载》
- .Net Core&RabbitMQ限制循环消费
- IQueryable和IEnumerable 快读《ASP.NET Core技术内幕与项目实战》EFCore2.5:集合查询原理揭秘
- .NET6打包部署到Windows Service
- api什么是api管理 api管理有什么作用
- ppapiflash插件是啥 ppapi插件是什么
- Dapr实现.Net Grpc服务之间的发布和订阅,并采用WebApi类似的事件订阅方式
- 是什么让.NET7的Min和Max方法性能暴增了45倍?
- 19 基于.NetCore开发博客项目 StarBlog - Markdown渲染方案探索
