范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

SpringBoot接口加解密全过程详解

  一、接口为什么要加密
  接口加密传输,主要作用:  敏感数据防止泄漏、  保护隐私、  防伪装攻击、  防篡改攻击、  防重放攻击  等等…  4个字概括: 保护数据!
  当然不是说接口加密后,就能完完全全的保护我们的数据,但至少能防一部分人拿到我们的数据。
  而且接口加密感觉逼格是不是高过一点!!!  二、加密思路1、加密简介
  加密算法有很多,在能加密又能解密的算法可分为:  非对称加密算法,常见: RSA  、 DSA  、 ECC
  特点:算法复杂,加解密速度慢,但安全性高,一般与对称加密结合使用(对称加密对内容加密,非对称对对称所使用的密钥加密)  对称加密算法,常见: DES  、 3DES  、 AES  、 Blowfish  、 IDEA  、 RC5  、 RC6
  特点:加密解密效率高,速度快,适合进行大数据量的加解密  2、加密流程
  思路:
  假设现在客户端是A,服务端是B,现在A要去B请求接口  1、A要向B发送信息,A和B都要产生一对用于加密的非对称加密公私钥(AB各自生成自己的公私钥)  2、A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。(AB互换公钥)  3、A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。(公钥加密只有私钥能解)  4、A将这个消息发给B(已经用B的公钥加密消息)。  5、B收到这个消息后,B用自己的私钥解密A的消息。其他人收到这个报文都无法解密,因为只有B才有B的私钥。
  虽然这样就实现了接口的加密方式,但是呢,非对称加密的加解密速度相比对称加密速度很慢,当传输的数据很大时就更加明显了。
  所以我们对称与非对称一起用,理解上面的流程之后,我们在其基础稍微改下:  在A给B发信息的时候,随机生成一个对称加密的密钥,然后用刚生成的密钥加密信息,然后用B的公钥加密刚生成的对称密钥。  A把加密的两个信息发送给B。B收到数据之后,先用自己的私钥解开得到对称密钥,然后再用解开的对称密钥解开对称加密的信息,最终得到A传来的信息。  三、代码实现在当下Java还是SpringBoot为主流框架工作面试必备,今天还是以它来举例。  加解密代码怎么写,这个时候网上已经有很多现成的库了,不用我们操心,我们想的是如何在接口加解密的时候不影响我们自己的业务,也就是不用更改我们已经写好的代码。  很多人的第一反应应该就是AOP吧,对的没错可以使用AOP进行环绕增强。也可以使用 @ControllerAdvice   对Controller进行增强(本文以它来做为例子)。  Spring 提供两个接口 RequestBodyAdvice  、 ResponseBodyAdvice  。实现它们,即可对 Controller  进行增强,第一个是在controller之前增强,第二个就是对controller 的返回值进行增强。  在spring启动的时候会对 RequestMappingHandlerAdapter  的 initControllerAdviceCache()  方法进行初始化。会去把有 @ControllerAdvice  的类进行注入。  1、自定义类
  下面就来实现上面的两个接口实现类代码  EncryptRequestAdvice.java这个类的功能就是在请求到controller之前就把前端传上来的数据解密好  我们还要校验是否有必要解密  @ControllerAdvice(basePackages = {"top.lrshuai.encrypt.controller"}) public class EncryptRequestAdvice implements RequestBodyAdvice {      @Autowired     private KeyConfig keyConfig;      /**      * 是否需要解码      */     private boolean isDecode;      @Override     public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {         // 方法或类上有注解         if (Utils.hasMethodAnnotation(methodParameter,new Class[]{Encrypt.class,Decode.class})) {             isDecode=true;             // 这里返回true 才支持             return true;         }         return false;     }      @Override     public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {         if(isDecode){             return new DecodeInputMessage(httpInputMessage, keyConfig);         }         return httpInputMessage;     }      @Override     public Object afterBodyRead(Object obj, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {         // 这里就是已经读取到body了,obj就是         return obj;     }      @Override     public Object handleEmptyBody(Object obj, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {         // body 为空的时候调用         return obj;     }  } 在上面实现类中需要重写: supports()  、 beforeBodyRead()  、 afterBodyRead()  、 handleEmptyBody()   方法  只有在 supports()   返回 true   后面的方法才会支持执行。在 RequestResponseBodyAdviceChain  有判断  我们可以在 beforeBodyRead()  这个方法进行解密处理。  在上面的代码中,我加了自定义注解,因为可能需求是这样的,有些接口加密有些接口不加密,用自定义注解比较方便。  然后 DecodeInputMessage   这个类是自定义实现了 HttpInputMessage  接口,解码逻辑都在里面。如下:  DecodeInputMessage.java
  这个类就是具体的解码逻辑了  public class DecodeInputMessage implements HttpInputMessage {      private HttpHeaders headers;      private InputStream body;      public DecodeInputMessage(HttpInputMessage httpInputMessage, KeyConfig keyConfig) {         // 这里是body 读取之前的处理         this.headers = httpInputMessage.getHeaders();         String encodeAesKey = "";         List keys = this.headers.get(Result.KEY);         if (keys != null && keys.size() > 0) {             encodeAesKey = keys.get(0);         }         try {             // 1、解码得到aes 密钥             String decodeAesKey = RsaUtils.decodeBase64ByPrivate(keyConfig.getRsaPrivateKey(), encodeAesKey);             // 2、从inputStreamReader 得到aes 加密的内容             String encodeAesContent = new BufferedReader(new InputStreamReader(httpInputMessage.getBody())).lines().collect(Collectors.joining(System.lineSeparator()));             // 3、AES通过密钥CBC解码             String aesDecode = AesUtils.decodeBase64(encodeAesContent, decodeAesKey, keyConfig.getAesIv().getBytes(), AesUtils.CIPHER_MODE_CBC_PKCS5PADDING);             if (!StringUtils.isEmpty(aesDecode)) {                 // 4、重新写入到controller                 this.body = new ByteArrayInputStream(aesDecode.getBytes());             }         } catch (Exception e) {             e.printStackTrace();         }     }      @Override     public InputStream getBody() throws IOException {         return body;     }      @Override     public HttpHeaders getHeaders() {         return headers;     } } 上面的代码注释我觉得都写的清楚了,不多介绍。  EncryptResponseAdvice.java这个类的主要功能就是对返回值进行加密操作  直接在 beforeBodyWrite()  里面执行具体的加密操作即可  supports()  方法也是需要返回 true  ,在 RequestResponseBodyAdviceChain.processBody()  中有个判断只有 supports()  返回 true  才会执行 beforeBodyWrite()   @Slf4j @ControllerAdvice(basePackages = {"top.lrshuai.encrypt.controller"}) public class EncryptResponseAdvice implements ResponseBodyAdvice {      @Autowired     private KeyConfig keyConfig;      @Override     public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {         // return true 有效         return true;     }      /**      * 返回结果加密      * @param obj 接口返回的对象      * @param methodParameter method      * @param mediaType  mediaType      * @param aClass HttpMessageConverter class      * @param serverHttpRequest request      * @param serverHttpResponse response      * @return obj      */     @Override     public Object beforeBodyWrite(Object obj, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {         // 方法或类上有注解         if (Utils.hasMethodAnnotation(methodParameter,new Class[]{Encrypt.class, Encode.class})) {             // 这里假设已经定义好返回的model就是Result             if (obj instanceof Result) {                 try {                     // 1、随机aes密钥                     String randomAesKey = AesUtils.generateSecret(256);                     // 2、数据体                     Object data = ((Result) obj).getData();                     // 3、转json字符串                     String jsonString = JSON.toJSONString(data);                     // 4、aes加密数据体                     String aesEncode = AesUtils.encodeBase64(jsonString, randomAesKey,keyConfig.getAesIv().getBytes(),AesUtils.CIPHER_MODE_CBC_PKCS5PADDING);                     // 5、重新设置数据体                     ((Result) obj).put(Result.DATA,aesEncode);                     // 6、使用前端的rsa公钥加密 aes密钥 返回给前端                     ((Result) obj).put(Result.KEY,RsaUtils.encodeBase64PublicKey(keyConfig.getFrontRsaPublicKey(),randomAesKey));                     // 7、返回                     return obj;                 } catch (Exception e) {                    log.error("加密失败:",e);                 }             }         }         return obj;     } }
  看代码注释,不说了。  2、加密工具类
  加密工具类,我在网上收集整理了一下,搞了个jar。直接在pom.xml 引入即可。如下:   	top.lrshuai.encryption 	encryption-tools 	1.0.3 
  自此核心代码都讲完了,这里只是给出了个demo,可以参考一下(代码写的也不是很好,很多地方也没有封装),加密方式多种多样,都是可以自由更改,这种加密方式不喜欢就改。
  差点忘记了,前端代码呢。  3、前端代码
  前端也是在Github分别找了两个库:  jsencrypt
  这个是RSA加密库,这个是在原版的 jsencrypt  进行增强修改,原版的我用过太长数据加密失败,多此加密解密失败,所以就用了这个库。  CryptoJS
  AES加密库,这个库是Google开源的,有AES、MD5、SHA 等加密方法
  然后我使用的是Vue写的简单页面(业余前端)  html            请求              
字段: Value:
userId:
userName:
age:
info:
AES密钥:
AES向量:
  

要发送的数据:{{parameter}}

加密后的数据:{{encodeContent}}   

收到服务端的内容:{{result}}

解密服务端AES密钥内容:{{decodeAes}}

最终拿到服务端的内容:{{decodeContent}}   主要看 testRequest() 这个方法就行了,都有代码注释。 注意点后端需要注意的就是,controller参数需要用 @RequestBody 包起来,如下: @PostMapping ( "/test1" )   @ResponseBody   public Object test1( @RequestBody (required = false) TestDto dto){   System.out.println( "dto=" +dto);   return Result.ok(dto);   } 而前端传上来的时候header 需要设置"Content-Type": "application/json;charset=utf-8" 最终效果   在上面的postman中 data :里面的数据就是aes加密后的数据 key :里面就是前端RSA公钥加密后的AES密钥(前端需要用私钥解密得到aes密钥,然后再用密钥解开data里面的数据) status :这个是状态码,如果报错了就不是200,不然报错了返回的数据,前端解几百年都解不开。 4、源码地址https://gitee.com/rstyro/spring-boot/tree/master/Springboot2-api-encrypt作者:rstyro 来源: https://rstyro.github.io/blog/2020/10/22/Springboot2接口加解密全过程详解(含前端代码)/


三大首发黑科技亮相!一加11挑战安卓四大不可能即将完成单单是看到挑战安卓四大不可能的口号,就会有很多网友开始期待一加11的发布了,毕竟,对于一个想要从底层去调整安卓手机使用痛点的旗舰手机,它的日常使用体验毕竟会得到行业的关注。而截止到一加11爆料消息汇总黑科技云集,性能影像拉满最近网友们对于一加品牌即将推出的一加11有着极高的关注与讨论度,这也是因为相比起现在厂商的挤牙膏更新,一加11给的东西有点多,这令外界十分惊喜。如果你还不太清楚状况产品,那接下来就百度发力虚拟人,女神叶悠悠深入人心,巩固输入法市场第一名!输入法是智能手机必不可少的软件之一,无论是安卓用户还是苹果用户,有很大一部分用户都会下载第三方输入法应用,而目前比较流行的第三方输入法,主要是百度搜狗和讯飞这三款。来自艾媒咨询的报马化腾发话后,腾讯荟聚不搞了在2022年最后一个工作日,微信服务入口(原来微信支付的九宫格入口)中的腾讯荟聚宣布将进行业务升级,由过去的货架式电商向品牌小程序推荐和发现服务转型,此前荟聚已宣布停止其荟聚豆产品节日多面手,年货天花板三星NeoQLED8KLifestyle艺术电视年节礼时值年终岁尾,又到了一年一度准备年货,和亲人团聚过年的时候,今年的数码年货大家准备选什么产品呢?家是庇护我们的港湾,也是亲情汇聚的地方,电视作为家庭的一员,不仅仅是客厅的娱乐中心,泰捷WE60PRO电视盒子全新升级带来越级体验进入后疫情时代,为了自己的健康和社会的有序运行,更多的人选择更多的时间来居家生活,无论是在家学习生活办公,闲暇之余都少不了娱乐一下,让身心保持轻松愉悦,这才是健康的表现,而追剧看视55岁英拉才是真名媛裙不过膝,衣穿成套,身材发福气质也高级很多人都觉得女人到了中年,穿裙子一定要选择过膝盖的长度,这样才显得更加端庄得体,可实际上,并不是所有女性都适合过膝裙,尤其是对于身材微胖,腿部线条不是很修长的女性,过膝裙很容易穿出最低调的兔年手表?喜欢八卦兔的读者,怕漏过新文,欢迎设为星标大家应该还记得,11月底我推荐过名士新表利维拉Baumatic月相腕表。大约一周后,就有读者欢欢喜喜来晒图了,果然是行动派。他秀完还问我,童瑶章子怡同穿风衣输太多!一个黑丝廉价俗气,一个裸腿高贵优雅风衣在日常生活当中是很受女性欢迎的单品,而且它不挑年龄性别身材和气质,只要懂得针对性的去挑选,就能够穿出干练飒爽的效果。大多数3040岁的中年女性,对于风衣都情有独钟,但为什么有的今日消费资讯城市画报将从2023年1月开始休刊lululemon长春首店开幕城市画报将从2023年1月开始休刊12月30日,城市画报宣布杂志将从2023年1月开始休刊。城市画报在1999年创刊,至今23年,共发行了462期杂志。杂志以自己的选题和内容审美与林妙可穿旗袍扮贵族小姐,结果身材珠圆玉润像50岁的大妈,好难看林妙可年纪轻轻的,就被亲妈给毁了,打扮太土气,即使穿着旗袍也不像贵族小姐,反而像大妈,难看死了!小时候的林妙可那么可爱苗条,但长大后就不行了,小胖墩儿一个,特别显老,不知道为什么。
市委书记不是谁都能演,怪异表情鸡窝头,观众看了都直摇头在狂飙原著里,孟德海和高启强那一条线似有隐喻,这位被市委书记架空的区委书记,最终选择和黑恶势力合作,成为驱虎吞狼的反噬者,想要借势,反被吞没。而当京海市长赵立冬落得个咎由自取的结局春暖花开的日子里,一起来庄行古镇文化会客厅看看春暖花开的日子里,来庄行古镇文化会客厅,走一走,看一看。徜徉冷江雨巷,去探寻老街历史,开启一段文化之旅。庄行古镇文化会客厅庄行古镇文化会客厅位于庄行老街一新路101号,共1200多2023年兔年宝宝起名测名字程姓男孩好听有涵养的名字程姓男孩好听有涵养的名字一姓程的男孩名字洋气点程青浩(qngho)姓名笔画81119画出自1张埴的赠云留道人其二往往诸公眼亦青,尚疑崔浩是前生。赏析青深绿色或浅蓝色,喻年轻,年少,历史思考罗马帝国时期,拉丁语及拉丁文化是如何普及的?历史开讲历史思考罗马帝国时期,拉丁语及拉丁文化是如何普及的?首先,在回答这个问题前,我们需要知道,随着众多罗马殖民城市的建立,在西部地区的钱币上,使用拉丁语的做法也越来越普遍,而且最傻老板于东来95年负债30万,今身价70亿,9成利润给员工中国只有两种超市,胖东来和其他。作为零售行业中神一般的存在,胖东来战胜了营业额超百亿的丹尼斯,让沃尔玛6年不敢开张营业。胖东来究竟有何魅力,为何会获得如今的地位?这就不得不提到它的人行员工做梦都能笑醒13万员工摇身变为公务员,支行撤销是好事今天,是一个特别的日子,两会选举了新一代的领导集体班子。也意味着两会即将接近尾声。而两会期间,几家欢喜几家愁,有人笑哭了,也有人睡觉也不一定睡得安稳。这次提出机构改革,对人民银行以怀孕期间孕妇可以使用手机吗?2022育儿季导读在怀孕的期间,我们总是会听到各种各样的辐射有害论,好像生活中各种电器都能和辐射挂上钩,动不动就说会影响到胎儿发育。而首当其冲的应该就是我们每天都在用的手机了,很多背叛生3胎老婆!东出昌大出轨少女毁事业,躲入深山劈柴隐居头条创作挑战赛今年35岁的日本男星东出昌大,过去因为外形帅气,从模特儿变成演员后,因演出NHK晨间剧多谢款待打响知名度,并与剧中女星渡边杏交往,两人结婚后,育有两女一子,婚姻跟事业今日电影科普可惜,这现象级爆款没法引进!香港名媛蔡天凤遇害,轰动整个香港。谁也想不到,前夫一家竟然把她迷晕,带到郊区出租屋内,用刮肉刀铁锤电锯等残忍碎尸。直到现在,尸体残骸还没有找全。不少人纳闷,这都2023年了,怎么还13岁王诗龄再上热搜,年少成名的她,为何非议不断?01hr最近王诗龄因为几句话,突然空降热搜了。关你什么事?你凭什么教我做事?你谁呀?我凭什么听你的?一连四个问,让网友直呼简直太爽了!这其中,究竟是怎么回事呢?02hr说起来,这事精品力作书写红色热土原创民族歌剧呼儿嘿哟在兰演出中国甘肃网3月9日讯(本网记者任磊)9日晚,由甘肃省歌剧院创排的原创民族歌剧呼儿嘿哟在兰州黄河剧院亮嗓开唱,该剧以南梁革命根据地发生的历史故事为原型,赓续红色血脉,书写红色热土,深