前言
前后端分离的开发方式,我们以接口为标准来进行推动,定义好接口,各自开发自己的功能,最后进行联调整合。无论是开发原生的APP还是webapp还是PC端的软件,只要是前后端分离的模式,就避免不了调用后端提供的接口来进行业务交互。
网页或者app,只要抓下包就可以清楚的知道这个请求获取到的数据,这样的接口对爬虫工程师来说是一种福音,要抓你的数据简直轻而易举。
数据的安全性非常重要,特别是用户相关的信息,稍有不慎就会被不法分子盗用,所以我们对这块要非常重视,容不得马虎。
如何保证API调用时数据的安全性?
- 通信使用https
- 请求签名,防止参数被篡改
- 身份确认机制,每次请求都要验证是否合法
- APP中使用ssl pinning防止抓包操作
- 对所有请求和响应都进行加解密操作
- 等等方案.......
对所有请求和响应都进行加解密操作
方案有很多种,当你做的越多,也就意味着安全性更高,今天我跟大家来介绍一下对所有请求和响应都进行加解密操作的方案,即使能抓包,即使能调用我的接口,但是我返回的数据是加密的,只要加密算法够安全,你得到了我的加密内容也对我没什么影响。
像这种工作最好做成统一处理的,你不能让每个开发都去关注这件事情,如果让每个开发去关注这件事情就很麻烦了,返回数据时还得手动调用下加密的方法,接收数据后还得调用下解密的方法。
为此,我基于Spring Boot封装了一个Starter, 内置了AES加密算法。GitHub地址如下:
github.com/yinjihuan/s…
先来看看怎么使用,可以下载源码,然后引入即可,然后在启动类上增加@EnableEncrypt注解开启加解密操作:
- @EnableEncrypt
- @SpringBootApplication
- public class App {
-
- public static void main(String[] args) {
- SpringApplication.run(App.class, args);
- }
- }
增加加密的key配置:
- spring.encrypt.key=abcdef0123456789
- spring.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件事情:
- 统一处理数据的响应,在渲染到页面之前进行解密操作
- 当有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;
- }
(编辑:ASP站长网)
|