.NET API 接口数据传输加密最佳实践记录
发布时间:2023-02-17 10:11:41 所属栏目:asp.Net 来源:互联网
导读:我们在做 Api 接口时,相信一定会有接触到要给传输的请求 body 的内容进行加密传输。其目的就是为了防止一些敏感的内容直接被 UI 层查看或篡改。 其实粗略一想就能想到很多种方案,但是哪些方案是目前最适合我们项目的呢? 硬编码方式 最先想到的应该就是硬
} 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) } } 为什么之前提到这种方案就“差不多”了呢,实际上上面这种方式在某些场景下会显得比较“累赘”。因为无论通过中间件和还是 IHttpModule 都会导致所有请求都会经过它,相当于增加了一个过滤器,如果这时候我要新增一个上传文件接口,那必然也会经过这个处理程序。说的更直接一点,如果碰到那些少数不需要加解密的接口请求那要怎么办呢? 其实上面可以进行拓展处理,比如对特定的请求进行过滤: if(context.Request.Path.Contains("upload")) { return; } 注意上述代码只是做个 demo 展示,真正还是需要通过如 context.GetRouterData() 获取路由数据进行精准比对。 当类似于这种需求开始变多以后(吐槽:谁知道业务是怎么发展的呢?)原来的中间件的“任务量”开始变得厚重了起来。到时候也会变得难以维护和阅读。 这个时候就是我目前较为满意的解决方案登场了,它就是模型绑定 ModelBinding。 模型绑定 回到需求的开端,不难发现,我们其实要是如何将前端加密后的请求体绑定到我们编写的接口方法中。这里面的过程很复杂,需要解析前端发起的请求,解密之后还要反序列化成目标接口需要的方法参数。而这个过程还要伴随着参数校验,如这个请求是否符合加密格式。而这个过程的一切都是模型绑定要解决的事。我们以 NETCore 版本为例子,讲一下大概的流程; 模型绑定的过程其实就是将请求体的各个字段于具体的 CLR 类型的字段属性进行一一匹配的过程。.NetCore 再程序启动时会默认提供了一些内置的模型绑定器,并开放 IModelBinderProvider 接口允许用户自定义模型绑定器。我们通过查看 MvcCoreMvcOptionsSetup 就清楚看到框架为我们添加 18 个自带的模型绑定器。以及如何调用的方式。 所以接下来我们很容易的可以一葫芦画瓢的照抄下来: public class SecurityTransportModelBinder : IModelBinder { ... public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } try { var request = bindingContext.HttpContext.Request; var model = await JsonSerializer.DeserializeAsync<SafeDataWrapper>(request.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }); var decryptContent = RsaHelper.Decrypt(model.Info, privateKey); var activateModel = JsonSerializer.Deserialize(decryptContent, bindingContext.ModelMetadata.ModelType, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }); //重新包装 if (activateModel == null) { bindingContext.Result = ModelBindingResult.Failed(); } else { bindingContext.Result = ModelBindingResult.Success(activateModel); } } catch (Exception exception) { bindingContext.ModelState.TryAddModelError( bindingContext.ModelName, exception, bindingContext.ModelMetadata); } _logger.DoneAttemptingToBindModel(bindingContext); //return Task.CompletedTask; } } 抄了 ModelBinder 还不行,还要抄 ModelBinderProvider: public class SecurityTransportModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.Metadata.IsComplexType && typeof(IApiEncrypt).IsAssignableFrom(context.Metadata.ModelType)) { var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>(); var configuration = context.Services.GetRequiredService<IConfiguration>(); return new SecurityTransportModelBinder(loggerFactory, configuration); } return null; (编辑:莱芜站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
- asp.net – 如何在Visual Studio中添加NUnit
- asp.net – WebForm_DoCallback定义
- asp.net-mvc – 如何在asp.net mvc中处理分页?
- asp.net – axd和ashx处理程序之间的区别
- asp.net-mvc – MVC 3布局页面,Razor模板和下拉列
- asp.net-mvc – 如何组合两个dataTextFields的Se
- webservice的两种调用方式
- asp.net-mvc – 什么是强类型的视图在ASP.NET MV
- 如何为Asp.Net中的所有子文件夹注册HttpHandler?
- asp.net – Jquery Ajax,不在Internet Explorer中
热点阅读