ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

NETAPI接口数据传输加密最佳实践

2022-11-05 20:37:34  阅读:252  来源: 互联网

标签:数据 浏览器 工具 导出 管理 结构


NETAPI接口数据传输加密最佳实践

我们在做Api接口时,相信一定会有接触到要为传输的请求body的内容进行数据加密。其目的就是为了避免一些敏感的内容直接被UI层查看或篡改。
其实粗略一想就能想到很多种方案,但是哪些方案是目前最适合我们项目的呢?
硬编码方式
最先想到的应该就是硬编码方式,就是哪个接口要进行传输加密,那么就针对该接口特别处理:
publicclassSecurityApiController{
 ...
 publicasyncTaskUpdateUser([FromBody]SecurityRequestrequest){
 varrequestBody=RsaHelper.Decrypt(privateKey,request.Content);
varuser=JsonHelper.Deserialize(requestBody);
 awaitUpdateUserAsync(user);
 returnnewResult(RsaHelper.Encrypt(publicKey,new{Success=true}));
 }
}
这种方式好处是简单明了,按需编程即可,不会对其它接口造成污染。
一旦这种需求越来越多,我们就会写大量以上的重复性代码;而对于前端而言亦是如此,因此当我们应该传输加密乃是最基本的需求时,上面硬编码的方式就显得很不合适了。
这时候我们可以采用统一入口的方式来实现
统一入口
回顾上边的硬编码方式,其实每个相接处的加解密处理从SRP原则上理解,不应该是接口的职责。所以需要把这部分的代码移到一个独立的方法,再加解密之后我们再把该请求调度到具体的接口。
这种方式其实有很多种实现方式,在这里我先说一下我司其中一个.NET4.5的项目采取的方式。
其实就是额外提供了一个统一的入口,全部需要传输加密的需求都走这一个接口:如http://api.example.com/security
publicclassSecurityController{
 ...
 publicasyncTaskEntryPoint([FromBody]SecurityRequestrequest){
 varrequestBody=RsaHelper.Decrypt(privateKey,request.Content);
 varuser=JsonHelper.Deserialize(requestBody);
 varobj=awaitDispathRouter(requestBody.Router,user);
returnnewResult(RsaHelper.Encrypt(publicKey,obj));
 }
 publicasyncTaskDispathRouter(Routerrouter,objectbody){
 ...
 TypeobjectCon=typeof(BaseController);
MethodInfomethInfo=objectCon.GetMethod(router.Name);
varresp=(Task)methInfo.Invoke(null,body);
returnawaitresp;
 }
}
很明显这是通过统一入口地址调用并配合反射来实现这种目的。
这种好处如前面所说,统一了调用入口,这样提高了代码复用率,让加解密不再是业务接口的一部分了。同样,这种利用一些不好的点;比如用了反射性能会受影响。而且我们过多进行统一了。我们看到这种方式只能把所有的接口方法都提及BaseController。因此我司项目的Controller部分,会看见大量如下的写法:
//文档UserController.cs
publicpartialclassBaseController{
 ...
}
//文档AccountController.cs
publicpartialclassBaseController{
}
//...
这样必然就会导致一个明显的问题,就是“代码爆炸”。这相当于把所有的领域模型全部灌输到一个控制器中,一开始写的时候方便了,但是后期维护以及交接换人的时候阅读代码是非常痛苦的一个过程。因为在不同Controller文件中一定会重复初始化一些模块,而我们在引用方法的时候IDE每次都会显示上千个方法,有时候还不得不查看哪些方法名一样或相近的具体意义。
针对上述代码爆炸的方式还有一种提高,就是将控制器的挑选开放给应用端,也就是将方法名和控制器名都作为请求参数暴露给前端,但是这样会加大前端的开发心智负担。
综上所述我是非常不建议采用这种方式的。虽说是很古老的.Net4/4.5的框架,但我们还是有其它相对更优雅的实现方式。
中间件
其实大家熟悉了.NETCore下的Middleware机制,我们会很容易的在.NETCore下实现如标题的这种需求:
//.NETCore版本
publicclassSecuriryTransportMiddleware{
privatereadonlyRequestDelegate_next;
publicRequestCultureMiddleware(RequestDelegatenext)
{
_next=next;
}
publicasyncTaskInvokeAsync(HttpContextcontext)
{
 //requesthandle
varencryptedBody=context.Request.Body;
varencryptedContent=newStreamReader(encryptedBody).ReadToEnd();
vardecryptedBody=RsaHelper.Decrypt(privateKey,encryptedContent);
varoriginBody=JsonHelper.Deserialize(decryptedBody);
varjson=JsonHelper.Serialize(dataSource);
varrequestContent=newStringContent(json,Encoding.UTF8,"application/json");
stream=awaitrequestContent.ReadAsStreamAsync();
context.Request.Body=stream;
await_next(context);
//responsehandle
varoriginContent=newStreamReader(context.Response.Body).ReadToEnd();
varencryptedBody=RsaHelper.Encrypt(privateKey,originContent);
varresponseContent=newStringContent(json,Encoding.UTF8,"application/json");
context.Response.Body=awaitresponseContent.ReadAsStreamAsync();
//或者直接
//awaitcontext.Response.WriteAsync(encryptedBody);
}
}
为了方便描述,以上代码我省略了必要的校验和异常错误处理
这样有什么好处呢?一个最明显的好处就是解耦了加解密与真正项目需求。对真正的业务代码几乎没有攻击性。其实我觉得业务开发能做到这里其实就差不多了,还有其它需求都能够基于这个中间件进行拓展开发。
那么在.NETFramwork没有中间件怎么办呢?
其实在.NETFramwork框架下IHttpModule能和中间件一样能做到这点:
publicclassSecurityTransportHttpModule:IHttpModule{
 ...
 publicvoidInit(HttpApplicationcontext){
 ...
 context.BeginRequest+=ContextBeginRequest;
 context.PostRequestHandlerExecute+=

标签:数据,浏览器,工具,导出,管理,结构
来源:

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有