本文转载自公众号: 猿天地


1、前言

前后端分离的开发方式,我们以接口为标准来进行推动,定义好接口,各自开发自己的功能,最后进行联调整合。无论是开发原生的APP还是webapp还是PC端的软件,只要是前后端分离的模式,就避免不了调用后端提供的接口来进行业务交互。

网页或者app,只要抓下包就可以清楚的知道这个请求获取到的数据,这样的接口对爬虫工程师来说是一种福音,要抓你的数据简直轻而易举。

数据的安全性非常重要,特别是用户相关的信息,稍有不慎就会被不法分子盗用,所以我们对这块要非常重视,容不得马虎。

2、如何保证API调用时数据的安全性?


  1. 通信使用https

  2. 请求签名,防止参数被篡改

  3. 身份确认机制,每次请求都要验证是否合法

  4. APP中使用ssl pinning防止抓包操作

  5. 对所有请求和响应都进行加解密操作

  6. 等等方案…….

3、对所有请求和响应都进行加解密操作

方案有很多种,当你做的越多,也就意味着安全性更高,今天我跟大家来介绍一下对所有请求和响应都进行加解密操作的方案,即使能抓包,即使能调用我的接口,但是我返回的数据是加密的,只要加密算法够安全,你得到了我的加密内容也对我没什么影响。

像这种工作最好做成统一处理的,你不能让每个开发都去关注这件事情,如果让每个开发去关注这件事情就很麻烦了,返回数据时还得手动调用下加密的方法,接收数据后还得调用下解密的方法。

为此,我基于Spring Boot封装了一个Starter, 内置了AES加密算法。GitHub地址如下:

https://github.com/yinjihuan/spring-boot-starter-encrypt

先来看看怎么使用,可以下载源码,然后引入即可,然后在启动类上增加@EnableEncrypt注解开启加解密操作:

@EnableEncrypt@SpringBootApplicationpublic class App {    public static void main(String[] args) {        SpringApplication.run(App.class, args);    }}

增加加密的key配置:

spring.encrypt.key=abcdef0123456789spring.encrypt.debug=false
  • spring.encrypt.key:加密key,必须是16位

  • spring.encrypt.debug:是否开启调试模式,默认为false,如果为true则不启用加解密操作

为了考虑通用性,不会对所有请求都执行加解密,基于注解来做控制。

响应数据需要加密的话,就在Controller的方法上加@Encrypt注解即可。

@Encrypt@GetMapping("/list")public Response queryNews(String city) {    return Response.ok(city);}

当我们访问/list接口时,返回的数据就是加密之后base64编码的格式。

还有一种操作就是前段提交的数据,分为2种情况,一种是get请求,这种暂时没处理,后面再考虑,目前只处理的post请求,基于json格式提交的方式,也就是说后台需要用@RequestBody接收数据才行, 需要解密的操作我们加上@Decrypt注解即可。

@Decrypt@PostMapping("/save")public Response savePageLog(@RequestBody PageLogParam logParam, HttpServletRequest request) {    pageLogService.save(logParam);    return Response.ok();}

加了@Decrypt注解后,前端提交的数据需要按照AES加密算法,进行加密,然后提交到后端,后端这边会自动解密,然后再映射到参数对象中。

上面讲解的都是后端的代码,前端使用的话我们以js来讲解,当然你也能用别的语言来做,如果是原生的安卓app也是用java代码来处理。

前端需要做的就2件事情:

  1. 统一处理数据的响应,在渲染到页面之前进行解密操作

  2. 当有POST请求的数据发出时,统一加密

js加密文件请参考我GitHub中encrypt中的aes.js,crypto-js.js,pad-zeropadding.js

我们以axios来作为请求数据的框架,用axios的拦截器来统一处理加密解密操作。

首先还是要封装一个js加解密的类,需要注意的是加密的key需要和后台的对上,不然无法相互解密,代码如下:

var key  = CryptoJS.enc.Latin1.parse('abcdef0123456789');var iv   = CryptoJS.enc.Latin1.parse('abcdef0123456789');// 加密function EncryptData(data) {    var srcs = CryptoJS.enc.Utf8.parse(data);    var encrypted = CryptoJS.AES.encrypt(srcs, key, {        mode : CryptoJS.mode.ECB,        padding : CryptoJS.pad.Pkcs7    });    return encrypted.toString();}// 解密function DecryptData(data) {    var stime = new Date().getTime();    var decrypt = CryptoJS.AES.decrypt(data, key, {        mode : CryptoJS.mode.ECB,        padding : CryptoJS.pad.Pkcs7    });    var result = JSON.parse(CryptoJS.enc.Utf8.stringify(decrypt).toString());    var etime = new Date().getTime();    console.log("DecryptData Time:" + (etime - stime));    return result;}

axios拦截器中统一处理代码:

// 添加请求拦截器axios.interceptors.request.use(function (config) {    // 对所有POST请加密,必须是json数据提交,不支持表单    if (config.method == "post") {        config.data = EncryptData(JSON.stringify(config.data));    }    return config;  }, function (error) {    return Promise.reject(error);});// 添加响应拦截器axios.interceptors.response.use(function (response) {    // 后端返回字符串表示需要解密操作    if(typeof(response.data) == "string"){        response.data = DecryptData(response.data);    }    return response;  }, function (error) {    return Promise.reject(error);});

到此为止,我们就为整个前后端交互的通信做了一个加密的操作,只要加密的key不泄露,别人得到你的数据也没用,问题是如何保证key不泄露呢?

服务端的安全性较高,可以存储在数据库中或者配置文件中,毕竟在我们自己的服务器上,最危险的其实就时前端了,app还好,可以打包,但是要防止反编译等等问题。

如果是webapp,则可以依赖于js加密来实现,下面我给大家介绍一种动态获取加密key的方式,只不过实现起来比较复杂,我们不上代码,只讲思路:

加密算法有对称加密和非对称加密,AES是对称加密,RSA是非对称加密。之所以用AES加密数据是因为效率高,RSA运行速度慢,可以用于签名操作。

我们可以用这2种算法互补,来保证安全性,用RSA来加密传输AES的秘钥,用AES来加密数据,两者相互结合,优势互补。

其实大家理解了HTTPS的原理的话对于下面的内容应该是一看就懂的,HTTPS比HTTP慢的原因都是因为需要让客户端与服务器端安全地协商出一个对称加密算法。剩下的就是通信时双方使用这个对称加密算法进行加密解密。

  1. 客户端启动,发送请求到服务端,服务端用RSA算法生成一对公钥和私钥,我们简称为pubkey1,prikey1,将公钥pubkey1返回给客户端。

  2. 客户端拿到服务端返回的公钥pubkey1后,自己用RSA算法生成一对公钥和私钥,我们简称为pubkey2,prikey2,并将公钥pubkey2通过公钥pubkey1加密,加密之后传输给服务端。

  3. 此时服务端收到客户端传输的密文,用私钥prikey1进行解密,因为数据是用公钥pubkey1加密的,通过解密就可以得到客户端生成的公钥pubkey2

  4. 然后自己在生成对称加密,也就是我们的AES,其实也就是相对于我们配置中的那个16的长度的加密key,生成了这个key之后我们就用公钥pubkey2进行加密,返回给客户端,因为只有客户端有pubkey2对应的私钥prikey2,只有客户端才能解密,客户端得到数据之后,用prikey2进行解密操作,得到AES的加密key,最后就用加密key进行数据传输的加密,至此整个流程结束。

4、spring-boot-starter-encrypt原理

最后我们来简单的介绍下spring-boot-starter-encrypt的原理吧,也让大家能够理解为什么Spring Boot这么方便,只需要简单的配置一下就可以实现很多功能。

启动类上的@EnableEncrypt注解是用来开启功能的,通过@Import导入自动配置类

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import({EncryptAutoConfiguration.class})public @interface EnableEncrypt {}

EncryptAutoConfiguration中配置请求和响应的处理类,用的是Spring中的RequestBodyAdvice和ResponseBodyAdvice,在Spring中对请求进行统计处理比较方便。如果还要更底层去封装那就要从servlet那块去处理了。

@Configuration@Component@EnableAutoConfiguration@EnableConfigurationProperties(EncryptProperties.class)public class EncryptAutoConfiguration {    /**     * 配置请求解密     * @return     */    @Bean    public EncryptResponseBodyAdvice encryptResponseBodyAdvice() {        return new EncryptResponseBodyAdvice();    }    /**     * 配置请求加密     * @return     */    @Bean    public EncryptRequestBodyAdvice encryptRequestBodyAdvice() {        return new EncryptRequestBodyAdvice();    }}

通过RequestBodyAdvice和ResponseBodyAdvice就可以对请求响应做处理了,大概的原理就是这么多了。

- END -

 往期推荐:

  • 死磕Java系列:

  1. 深入分析ThreadLocal

  2. 深入分析synchronized的实现原理

  3. 深入分析volatile的实现原理

  4. Java内存模型之happens-before

  5. Java内存模型之重排序

  6. Java内存模型之分析volatile

  7. Java内存模型之总结

  8. J.U.C之AQS简介

……

  • Spring系列:

  1. Spring Cloud Zuul中使用Swagger汇总API接口文档

  2. Spring Cloud Config Server迁移节点或容器化带来的问题

  3. Spring Cloud Config对特殊字符加密的处理

  4. Spring Boot使用@Async实现异步调用:使用Future以及定义超时

  5. Spring Cloud构建微服务架构:分布式配置中心(加密解密)

  6. Spring Boot快速开发利器:Spring Boot CLI

……

号外:

最近在做几个有意思的开源项目,感兴趣的朋友可以看看。

地址:

https://github.com/dyc87112/swagger-butler

可关注我的公众号

深入交流、更多福利

扫码加入我的知识星球


点击“阅读原文”,看本号其他精彩内容

前后端API交互如何保证数据安全性?相关推荐

  1. ajax配合ssm框架,SSM框架前后端信息交互实现流程详解

    SSM框架前后端信息交互实现流程详解 比如该处代码,显示了问题的标题信息,并将其作为超链接,点击该链接时进入后端Controller类的方法,并向其发送问题编号question_id 3.ajax请求 ...

  2. 后端程序设计课设,基于Java面向对象思想,MySQL数据库,Tomcat服务器实现网上商城网站。前后端分离开发思想,实现前后端信息交互。

    文章目录 项目展示 开发环境 使用关键技术 项目实现的主要功能 项目完成效果 项目技术核心介绍 MVC开发模式 Ajax实现前后端通信 MySQL数据库连接(使用连接池) 自动生成验证码程序 项目源代 ...

  3. umail邮件服务器如何保证数据安全性?

    U-mail邮件服务器如何保证数据安全性? 1.Umail全面支持SSL协议,可以通过https访问Webmail,使用SSL协议访问SMTP,IMAP.POP: 2.umail 内嵌全球顶级的反垃圾 ...

  4. SpringMVC获取前端传来的json数据的四种方法(前后端json交互总结)

    一.导包 一定要有 Jackson 的jar包依赖,就算有了fastjson,也要有Jackson包 <dependency><groupId>com.fasterxml.ja ...

  5. 点击某个物体人机验证码java,captcha: 行为验证码(滑动拼图、点选文字),前后端(java)交互,包含h5/flutter/uni-app的源码和实现...

    uni-app在线体验(微信小程序,请使用微信扫一扫) uni-app H5页面在线体验(扫一扫)        微信小程序                  uni-app H5 如果图片未能正常展 ...

  6. 前后端API接口安全问题,防止抓包恶意请求

    哈喽,你们好,这是我第一次发帖子,最近遇到了一些关于后端api接口的安全问题,相信很多刚开始接触前后端的人都会遇到这样的问题,如果后端写了一个数据库操作的接口供前端使用,而这些接口无论是GET请求还是 ...

  7. 个人记录——前后端api对接的一种方式

    两人或多人协作开发前后端分离项目,需要有一个api文档.例如后端人员编写api文档,前端人员如何才能查看到实时的文档,以此方便地在前端页面写入正确的交互接口(例如 ajax里type为get,url为 ...

  8. 前后端分离html ssm,前后端分离请求ssm返回数据

    当你的开发是前后端分离时,前台发起ajax请求,请求后台数据时会出现跨域问题,为前后台开发人员带来很多不便,如果你用的是springMVC,那么这个问题在后台非常好解决. springMVC为我们提供 ...

  9. A16.从零开始前后端react+flask - 将前端数据保存到数据库

    上一节,我们讲了如何将前后端联系起来. A15.从零开始前后端react+flask - 将前后端联系起来 https://blog.csdn.net/GreatXiang888/article/de ...

最新文章

  1. Java移位运算之算术右移位
  2. python怎么自学、可以达到什么程度-Python学到什么程度才算精通?天津Python培训...
  3. java面向对象思想如何理解
  4. 干掉 if 语句,一个不留的那种!
  5. 学习opengl(起步)
  6. Linux服务器编程之:chown()函数,chown命令
  7. python安装报错ox000007b_Python沙箱逃逸的n种姿势
  8. TCP/IP 网络编程 (三)
  9. .bin 文件用excel文件打开_bin文件怎么打开呢?
  10. properties配置文件的加密
  11. Idea搭建一个JavaWeb项目(一)
  12. 云计算 码率适配限速_5G 成熟后,带宽足够且云计算力够大,会不会对 PC 的升级需求放缓?...
  13. Python实现遗传算法解决TSP问题
  14. 致加西亚的信 谁动了我的奶酪
  15. element 按钮样式 点击后发生改变(完整改变element按钮样式)
  16. http 411错误
  17. 使用MapReduce统计一篇微博数据的点赞次数,并且输出前五个最高的点赞数量。
  18. 清华北大2021毕业生就业报告出炉!清华博士0人出国,70%进体制
  19. 查看主机是不是虚拟机
  20. LINUX CMA 初探

热门文章

  1. cpu密集型 计算密集型 io密集型 简介
  2. linux expect 自动交互 执行命令 超时 不完整 中断 解决方法
  3. docker 容器互访三种方式
  4. python3.8 新特性
  5. 编写 Debugging Tools for Windows 扩展,第 3 部分:客户端和回调 (windbg 插件 扩展)
  6. C语言中的extern关键字用法
  7. DevicePass-through及网卡的直接分配在Xen里面的实现
  8. 红黑树:自平衡的二叉查找树
  9. 端口复用及其实现分析[Google Patch]
  10. bp 字母识别 java_Matlab实现BP网络识别字母