当前位置: 首页 > 科技观察

前后端API交互如何保障数据安全?

时间:2023-03-14 12:03:30 科技观察

前言我们以接口为标准,提倡前后端分离的开发方式,定义接口,开发各自的功能,最后进行联合调整和集成。无论是开发原生APP、webapp还是PC端软件,只要前后端分离,就不可避免地要调用后端提供的接口进行业务交互。对于网页或者APP,只要抓包就可以清楚的知道这个请求获取到的数据。这样的接口对于爬虫工程师来说是福音。获取数据很容易。数据安全非常重要,尤其是与用户相关的信息,一不小心就可能被不法分子窃取,所以我们必须高度重视,不能马虎。调用API时如何保证数据安全?通信采用HTTPS请求签名,防止参数被篡改。身份确认机制验证每个请求是否合法。APP中使用了SSLpinning来防止抓包。所有请求和响应都经过加密和解密。操作及其他方案.......对所有的请求和响应进行加密和解密的方案有很多种。当您做得更多时,就意味着更高的安全性。今天给大家介绍一下所有的请求和响应都是加密解密的。即使你能抓包,即使你能调用我的接口,我返回的数据也是加密的。只要加密算法足够安全,你得到我的加密内容与我无关。影响。这种工作是统一处理的。你不能让每个开发人员都关注这件事。如果让每个开发者都去关注这件事情,那就很麻烦了。返回数据时需要手动调用加密方法,收到数据后需要调用解密方法。为此,我封装了一个基于SpringBoot的Starter,内置了AES加密算法。GitHub地址如下:github.com/yinjihuan/s...先来看看怎么用吧。可以下载源码,然后导入,然后在启动类上加上@EnableEncrypt注解,开启加解密操作:@EnableEncrypt@SpringBootApplicationpublicclassApp{publicstaticvoidmain(String[]args){SpringApplication.run(App.class,args);}}添加加密密钥配置:spring.encrypt.key=abcdef0123456789spring.encrypt.debug=falsespring.encrypt.key:加密密钥,必须为16位spring.encrypt.debug:是否开启调试模式,默认为false,为true则不开启加解密操作。为了考虑通用性,不会对所有请求都进行加解密。如果控制响应数据需要基于注解进行加密,只需在Controller方法中添加@Encrypt注解即可。@Encrypt@GetMapping("/list")publicResponsequeryNews(Stringcity){returnResponse.ok(city);}当我们访问/list接口时,返回的数据经过加密后是base64编码格式。另外一个操作就是上一节提交的数据,分为两种情况,一种是get请求,暂时没有处理,后面再考虑。目前只处理post请求,基于json格式提交的方式,也就是说后台需要使用@RequestBody来接收数据,我们可以在需要的操作上加上@Decrypt注解被解密。@Decrypt@PostMapping("/save")publicResponsesavePageLog(@RequestBodyPageLogParamlogParam,HttpServletRequestrequest){pageLogService.save(logParam);returnResponse.ok();}添加@Decrypt注解后,前端提交的数据需要加密根据AES算法加密,然后提交给后台,后台会自动解密,然后映射到参数对象。以上解释均为后端代码。前端使用,我们会用js来说明。当然你也可以用其他语言来做。如果是原生Android应用,也是用java代码处理的。前端需要做的只有两件事:统一处理数据响应,在渲染到页面之前进行解密。发送POST请求的数据时,统一加密js加密文件。请参考我GitHub中encrypt中的aes.js和crypto。-js.js,pad-zeropadding.js我们使用axios作为请求数据的框架,使用axios的拦截器统一处理加解密操作。首先我们需要封装一个js加解密类。需要注意的是,加密后的密钥需要与后台匹配,否则无法相互解密,代码如下:varkey=CryptoJS.enc.Latin1.parse('abcdef0123456789');variv=CryptoJS.enc.Latin1。parse('abcdef0123456789');//加密函数EncryptData(data){varsrcs=CryptoJS.enc.Utf8.parse(data);varencrypted=CryptoJS.AES.encrypt(srcs,key,{mode:CryptoJS.mode.ECB,padding:CryptoJS.pad.Pkcs7});returnencrypted.toString();}//解密函数DecryptData(data){varstime=newDate().getTime();vardecrypt=CryptoJS.AES.decrypt(data,key,{mode:CryptoJS.mode.ECB,填充:CryptoJS.pad.Pkcs7});varresult=JSON.parse(CryptoJS.enc.Utf8.stringify(decrypt).toString());varetime=newDate().getTime();console.log("解密数据时间:"+(etime-stime));returnresult;}axios拦截器中统一处理代码://添加请求拦截器axios.interceptors.request.use(function(config){//请对所有POST进行加密,必须是json数据提交,不支持formif(config.方法=="post"){config.data=EncryptData(JSON.stringify(config.data));}returnconfig;},function(error){returnPromise.reject(error);});//添加响应拦截器axios.interceptors.response.use(function(response){//后端返回一个字符串表示需要解密操作if(typeof(response.data)==”string”){response.data=DecryptData(response.data);}returnresponse;},function(error){returnPromise.reject(error);});至此,我们就对整个前后端通信通信做了一次加密操作,只要加密的key不是泄露了,别人能拿到你的数据也没用,问题是如何保证密钥不泄露?服务器的安全性比较高,可以存入数据库或者配置文件,毕竟靠我们自己server,最危险的其实是前端,app还好,可以打包,但是要防止反编译等问题,如果是webapp,可以realized靠的是js加密。下面介绍一种动态获取加密密钥的方法,但是实现起来比较复杂。我们不会上传代码。只说思路:加密算法有对称加密和非对称加密,AES是对称加密,RSA是非对称加密。之所以使用AES来加密数据,是因为它的效率高。RSA运行缓慢,可用于签名操作。我们可以利用这两种算法互补来保证安全性。RSA用于加密AES的秘钥,AES用于加密数据。两者结合,优势互补。其实如果你了解HTTPS的原理,你应该看看下面的内容我明白HTTPS之所以比HTTP慢是因为客户端和服务端需要安全地协商一个对称加密算法。剩下的就是双方在通信过程中使用这种对称加密算法进行加密和解密。客户端启动,向服务器发送请求时,服务器使用RSA算法生成一对公钥和私钥,我们简称为pubkey1和prikey1,并将公钥pubkey1返回给客户端。客户端得到服务器返回的公钥pubkey1后,利用RSA算法生成一对公钥和私钥,我们简称为pubkey2和prikey2,并用公钥pubkey1加密公钥pubkey2,然后加密后传输到服务器。此时服务端收到客户端传过来的密文,用私钥prikey1解密,因为数据是用公钥pubkey1加密的,通过解密可以得到客户端生成的公钥pubkey2,然后自己生成对称加密。这是我们的AES。其实就是相对于我们配置的长度为16位的加密密钥。生成这个密钥后,我们用公钥pubkey2加密后返回给客户端,因为只有客户端才有pubkey2对应的私钥。密钥prikey2只能由客户端解密。客户端拿到数据后,使用prikey2解密运算得到AES加密密钥。最后用加密密钥对数据传输进行加密,整个过程结束。spring-boot-starter-encrypt的原理***下面简单介绍一下spring-boot-starter-encrypt的原理,让大家明白为什么SpringBoot这么方便,通过简单的配置就可以实现很多功能。启动类上的@EnableEncrypt注解用于开启功能,自动配置类通过@Import@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import({EncryptAutoConfiguration.class})Public@interfaceEnableEncrypt{}EncryptAutoConfiguration配置请求和响应处理类,使用Spring中的RequestBodyAdvice和ResponseBodyAdvice。在Spring中对请求进行统计处理更加方便。如果要在更底层封装,就得从servlet来处理。@Configuration@Component@EnableAutoConfiguration@EnableConfigurationProperties(EncryptProperties.class)publicclassEncryptAutoConfiguration{/***配置请求解密*@return*/@BeanpublicEncryptResponseBodyAdviceencryptResponseBodyAdvice(){returnnewEncryptResponseBodyAdvice()*}/ret***BeanpublicEncryptRequestBodyAdviceencryptRequestBodyAdviceRequest(){returnEncryptAdvice();}}