代码编织梦想

 

1、前言

 

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

 

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

 

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

 

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

 

  1. 通信使用https
  2. 请求签名,防止参数被篡改
  3. 身份确认机制,每次请求都要验证是否合法
  4. APP中使用ssl pinning防止抓包操作
  5. 对所有请求和响应都进行加解密操作

 

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

 

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

 

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

 

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

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

 

先来看看怎么使用,可以下载源码,然后引入即可,然后在启动类上增加@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件事情:

  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就可以对请求响应做处理了,大概的原理就是这么多了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42290901/article/details/115628971

前后端分离架构:web实现前后端分离,前后端解耦_山河远阔的博客-爱代码爱编程_前后端解耦

一、前言        ”前后端分离“已经成为互联网项目开发的业界标杆,通过Tomcat+Ngnix(也可以中间有个Node.js),有效地进行解耦。并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如:浏览器,车载终端,安卓,IOS等等)打下坚实的基础。        前后端分离(解耦)的核心思想是:前端Html

前后端分离架构概述_georgiastar的博客-爱代码爱编程_前后端分离

1、背景        前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、

浅谈前后端分离及restful api_alexgeek的博客-爱代码爱编程_restful与前后端分离

一、综述        前端、后端这两个名词无数次出现在专业应用当中。从最开始不懂得网站上的内容从何而来,到现在经手几个项目后对前后端和互联网有了专业上的粗浅认知,所学越多,需学越多。当专业课上还在讲解着基于C#的ASP.NET开发中,如何拖动Button按钮,如何“快速”构建出一个所谓的前端,如何点击进入相应的后端语句时,前后端分离技术早已横行于世。顾

前后端分离下的前端架构选型-爱代码爱编程

一.主要目标 1.前后端解耦。前端主要任务是将原有页面中的大量的Python Flask框架里的jinja2模板内容给替换,采用纯粹的JavaScript模板引擎来进行解耦。 2.前后端分离。前端拥有自己的静态资源服务器和

前后端api交互如何保证数据安全性?_weixin_34009794的博客-爱代码爱编程

前言 前后端分离的开发方式,我们以接口为标准来进行推动,定义好接口,各自开发自己的功能,最后进行联调整合。无论是开发原生的APP还是webapp还是PC端的软件,只要是前后端分离的模式,就避免不了调用后端提供的接口来进行业务交互。 网页或者app,只要抓下包就可以清楚的知道这个请求获取到的数据,这样的接口对爬虫工程师来说是一种福音,要抓你的数据

前后端分离技术架构概述(转载)_jsonstr_猿的博客-爱代码爱编程

1、背景        前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如:浏览器,车载终端,安卓,IOS等等)打下坚实的基础。这个步骤是系统架构从猿进化成人的必经之路。      

前后端分离架构-爱代码爱编程

一、概述 前后端分离 在前后端分离的应用模式中,后端仅返回前端所需的数据,不再渲染HTML页面,不再控制前端的效果。至于前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端自己决定,网页有网页的处理方式,App有App的处理方式,但无论哪种前端,所需的数据基本相同,后端仅需开发一套逻辑对外提供数据即可。 在前后端分离的应用模式

前后端分离微服务架构如何设计?-爱代码爱编程

点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达! 一、职责划分 前端 前端工作专注业务的页面呈现,非常注重用户体验度,也是与各种角色打交道最多的。 比如: 前端开发人员会经常与产品经理或者客户讨论页面样式、视觉效果,页面布局等各种页面渲染效果前端开发人员要与UI设计师对接:字体大小、颜色、页面布局、样式等前端开发人员与多个后端

前后端分离架构中的接口安全_如何立即确保您的应用架构安全:分离,配置和访问-爱代码爱编程

前后端分离架构中的接口安全 如果您是忙碌的开发人员,那么本文将是构建安全应用程序体系结构的一个很好的起点。 (If you're a busy developer, this article will be a good starting point for building secure application architecture.)

Java Web前后端分离架构-爱代码爱编程

前后端分离的演变 记得12年从事工作的时候公司还没有专门的前端人员,一般我们都是前后端都会,毕竟那时候H5才刚刚起来微软的XP还在流行使用(默认系统自带IE6),IE的市场份额还是蛮大的。做的产品也没有很炫酷的特效(如果有也会选择使用flex),那时候Flash 是超级火的......扯得有点远了。 在开发的时候也是一边API接口服务,一边开发页面,发布

前后端分离架构优缺点分析整理,说的太好了!-爱代码爱编程

作者:fuzhongmin05 blog.csdn.net/fuzhongmin05/article/details/81591072 1、背景 前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构

java开发本科应届生薪资大概是多少?外行人最少15k,25k是人均水平...-爱代码爱编程

前两天有个互联网无关专业的高中老同学来问我薪资,他竟然觉得计科本科15k垫底,25k人均,不由让我再次瑟瑟发抖。 所以我决定写一篇只针对本科生应届生的文章。 想要切实的了解下本科生的真实数据,请不要走开,本文没有任何的吹牛逼! 2021应届生各大厂薪资表 如果是近两年,能拿到BAT等大厂offer的,的确是15K垫底,25K人均,ssp到年薪5