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

springgateway实现接口数据加密传输

  在一些对安全要求很高的系统,需要对数据进行加密传输,我们可以采用在网关加密解密数据传输提高系统安全性,加密解密算法使用rsa(相对性能影响较小),java代码如下import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; import com.google.common.base.Joiner; import io.netty.buffer.ByteBufAllocator; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.Lists; import org.apache.commons.lang3.StringUtils; import org.reactivestreams.Publisher; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpResponseDecorator; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono;  import java.net.URI; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.concurrent.atomic.AtomicReference;  import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR;  /**  * @ClassName AppFilter  * @Description TODO  * @Author ljq  * @Date 2022/12/13 16:16  * @Version 1.0  */ @Slf4j @RefreshScope @Component public class AppFilter implements GlobalFilter, Ordered {      private static Joiner joiner = Joiner.on("");      @Override     public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {         //如果存在appId 走应用认证接口         ServerHttpRequest request = exchange.getRequest();         String appId = request.getHeaders().getFirst("appId");         if(StringUtils.isNotBlank(appId)){             if (exchange.getRequest().getMethod().equals(HttpMethod.POST)) {                 String bodyStr = getBodyStr(exchange.getRequest().getBody());                 log.info("加密原始数据"+bodyStr);                 //重新封装请求 因为请求体内容已被消费,需要重新写入                 URI uri = request.getURI();                 request = request.mutate().uri(uri).build();                  //这块需要掉用微服务进行应用权限校验 并返回应用公私钥 这里使用hutu工具包 对数据进行rsa加解密 start                 String privateKey = "30820155020100300d06092a864886f70d01010105000482013f3082013b020100024100b9c7d70130df32ff4f41f79390fc085439e917a632b2707c0d3d4c8da0cedc22e55d66ddbe59287b16aa63ff3a98d23e3938da0ceabac4167204e09a3a0cd88f020301000102401f5ae821ce52cd73a3b7d98631612832b6f76d4362a9152d0abafed1a4836549c042700fc26b750a460c999c9a0107aec4cdfecde897606dcc56bb653aee1a89022100f773cf5f947e4eb442b8a2ba42929a557e2b6c48869347296fe6e5a5c7e12513022100c032ac9e7c2ca7ca817bdd8626fe25f427188c10bc42206fd3605764f767ba15022100f0653ded29219bec5b756c016f736523f132d63b8f21bd5c702deca4258e80a9022043e3625fd4c2bd3de580c81db3b63fd7bedb87d5fd796a15b5d728e78c104285022100879796fca38aadf54a0dd90959d1eef452fffe504d73dbaff887f5089e36cd19";                 String publicKey = "305c300d06092a864886f70d0101010500034b003048024100b9c7d70130df32ff4f41f79390fc085439e917a632b2707c0d3d4c8da0cedc22e55d66ddbe59287b16aa63ff3a98d23e3938da0ceabac4167204e09a3a0cd88f0203010001";                 RSA rsa = SecureUtil.rsa(privateKey,publicKey);                 bodyStr = rsa.decryptStr(bodyStr, KeyType.PrivateKey);                 log.info("解密数据:"+bodyStr);                 //这块需要掉用微服务进行应用权限校验 并返回应用公私钥 这里使用hutu工具包 对数据进行rsa加解密 end                 //将解密数据封装向下传递                 DataBuffer bodyDataBuffer = stringBuffer(bodyStr);                  Flux bodyFlux = Flux.just(bodyDataBuffer);                 request = new ServerHttpRequestDecorator(request) {                     @Override                     public Flux getBody() {                         return bodyFlux;                     }                 };                  //可以选择对返回体也进行加密                 ResBodyEncryptDecorator responseDecorator = new ResBodyEncryptDecorator(exchange.getResponse(),exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR),rsa);                  ServerHttpRequest newRequest = request.mutate().build();                 return chain.filter(exchange.mutate().request(newRequest).response(responseDecorator).build());             }else{                 //可以将get请求也设置特定的参数读取加解密 可以照着post请求做                 return AppIdInvalid(exchange);             }         }else{             return AppIdInvalid(exchange);         }      }      public static class ResBodyEncryptDecorator extends ServerHttpResponseDecorator{          private DataBufferFactory bufferFactory;          private String contentType;          private RSA rsa;          public ResBodyEncryptDecorator(ServerHttpResponse delegate,String contentType,RSA rsa) {             super(delegate);             this.contentType = contentType;             this.bufferFactory = delegate.bufferFactory();             this.rsa = rsa;         }          @Override         public Mono writeWith(Publisher<? extends DataBuffer> body) {             log.info("得到响应体");             if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {                 // 获取响应 ContentType                 // 记录 JSON 格式数据的响应体                 if (!StringUtils.isEmpty(contentType) && contentType.contains(MediaType.APPLICATION_JSON_VALUE)) {                     Flux<? extends DataBuffer> fluxBody = Flux.from(body);                     // 解决返回体分段传输                     return super.writeWith(fluxBody.buffer().map(dataBuffers -> {                         List list = Lists.newArrayList();                         dataBuffers.forEach(dataBuffer -> {                             byte[] content = new byte[dataBuffer.readableByteCount()];                             dataBuffer.read(content);                             DataBufferUtils.release(dataBuffer);                             list.add(new String(content, Charset.forName("UTF-8")));                         });                         String responseData = joiner.join(list);                         log.info("得到响应体内容:{}", responseData.replaceAll(" ","").replaceAll("	",""));                         responseData = rsa.encryptBase64(responseData, KeyType.PublicKey);                         return bufferFactory.wrap(responseData.getBytes());                     }));                 }             }             return super.writeWith(body);         }     }      /**      * token 无效,消息返回      * @param exchange      * @return      */     private Mono AppIdInvalid(ServerWebExchange exchange) {         ServerHttpResponse response = exchange.getResponse();         byte[] bits = "{"result":"-1","message":"应用不存在","data":null}".getBytes(StandardCharsets.UTF_8);         DataBuffer buffer = response.bufferFactory().wrap(bits);         response.setStatusCode(HttpStatus.UNAUTHORIZED);         //指定编码,否则在浏览器中会中文乱码         response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");         return response.writeWith(Mono.just(buffer));     }       /**      * 获取请求体内容      * @param body      * @return      */     private String getBodyStr(Flux body) {         AtomicReference bodyRef = new AtomicReference<>();         body.subscribe(buffer -> {             CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());             DataBufferUtils.release(buffer);             bodyRef.set(charBuffer.toString());             log.info(charBuffer.toString());         });         //获取request body         return bodyRef.get();       }      private DataBuffer stringBuffer(String value) {         byte[] bytes = value.getBytes(StandardCharsets.UTF_8);          NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);         DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);         buffer.write(bytes);         return buffer;     }      public static void main(String[] args) {         String privateKey = "30820155020100300d06092a864886f70d01010105000482013f3082013b020100024100b9c7d70130df32ff4f41f79390fc085439e917a632b2707c0d3d4c8da0cedc22e55d66ddbe59287b16aa63ff3a98d23e3938da0ceabac4167204e09a3a0cd88f020301000102401f5ae821ce52cd73a3b7d98631612832b6f76d4362a9152d0abafed1a4836549c042700fc26b750a460c999c9a0107aec4cdfecde897606dcc56bb653aee1a89022100f773cf5f947e4eb442b8a2ba42929a557e2b6c48869347296fe6e5a5c7e12513022100c032ac9e7c2ca7ca817bdd8626fe25f427188c10bc42206fd3605764f767ba15022100f0653ded29219bec5b756c016f736523f132d63b8f21bd5c702deca4258e80a9022043e3625fd4c2bd3de580c81db3b63fd7bedb87d5fd796a15b5d728e78c104285022100879796fca38aadf54a0dd90959d1eef452fffe504d73dbaff887f5089e36cd19";         String publicKey = "305c300d06092a864886f70d0101010500034b003048024100b9c7d70130df32ff4f41f79390fc085439e917a632b2707c0d3d4c8da0cedc22e55d66ddbe59287b16aa63ff3a98d23e3938da0ceabac4167204e09a3a0cd88f0203010001";         RSA rsa = SecureUtil.rsa(privateKey,publicKey);         String data = "{ " +                 "    "current":1, " +                 "    "size":20, " +                 "    "param":{ " +                 "        "afterSale":"Y", " +                 "        "commitTimeStart":"2011-11-11 00:00:00" " +                 "    } " +                 "}";         String encrypt = rsa.encryptBase64(data, KeyType.PrivateKey);         String decypt = rsa.decryptStr(encrypt, KeyType.PublicKey);         System.out.println(encrypt);         System.out.println(decypt);         encrypt = rsa.encryptBase64(data, KeyType.PublicKey);         decypt = rsa.decryptStr(encrypt, KeyType.PrivateKey);         System.out.println(encrypt);         System.out.println(decypt);     }      @Override     public int getOrder() {         return -2;     } }
  遇到的问题:
  1 有可能无法获取到请求体里面的内容可以参考 https://zhuanlan.zhihu.com/p/471402045
  效果:
  postman请求
  服务器日志

六七十年代,上高中难不难?怎样才能上高中?上世纪七十年代上高中不太难。我是一九七七年上的高中,就在我们公社中学的高中部学习,一九七九年毕业。当时我们公社有两所中学。一所在公社所在地敖桥,就叫敖桥中学。这所中学地处山区与丘陵我想买彩票,又觉得是骗局,你买彩票最多中过多少钱?我自己大乐透最高中过17。43万。扣完税13万多一点。这个完全就是给彩民打错了,彩民不要了,然后我自己留下了,没想到最后中了二等奖竞彩最高中过10万多一点。这个是店里的合买单子。当如何评价厦门现在的发展?厦门应该不需要盲目的去追求什么GDP啦人口规模啦城市规模什么的,一定要走自己的高端路线,就是要大力发展自己的第三产业,把高端服务业放在首位。把城市环境卫生医疗教育软件旅游会展金融高注册安全工程师没有用处为什么还有那么多人去考?有人说,注册安全工程师白考了,证书只能拿来垫桌底,真的是这样吗?今天学吧考培网校给大家来吃个定心丸,注册安全工程师还有这些你不知道的用处,赶紧考下来吧!用处一一证两用,可用来评职称惠州仲恺楼盘销量如何?仲恺楼市还有发展前景吗?仲恺高新区的房子太多了,去年火了一波后,今年又开始卖不动了。仲恺大道改造,据说还要比肩深南大道,这是极其荒诞搞笑的,深南大道2侧都是写字楼,仲恺大道改造2侧全是住宅楼和商铺,几乎没本人不明白,为什么要进行全员核酸检测?不晓得为啥老是一遍一遍核酸。是为了不传染给家人?直接所有人员居家21天,不发病的也就那样了,发病的拉走,用得着一遍一遍核酸吗,反正居家也传染不了别人。平时生活用品小区找人放到专门地10月1日起!土地归并,每亩补9万,这件事是真的吗?10月1日起!土地归并,每亩补9万,这件事是真的吗?哈哈!一个很有意思的问题。9万元是怎么求岀来啊?土地为什么会在10月1日归并?要归并也要等到农闲时节。农村的土地承包关系,按照上王者荣耀赛季奖励是上过的最高段位还是当前段位?诚邀,赛季奖励对于每个游戏来说是不一样的,英雄联盟,王者荣耀,球球大作战等当下热门游戏各不相同。对于英雄联盟来说,是按照赛季结束时段位发放奖励的。王者荣耀是在这个排位赛周期中,达到女儿无论如何也不肯去打疫苗,不打会不会有事?不打不会有任何事,南京疫情就是一个例子,如果有人变相强制接种,打12345反应,记得录音,也可以向国务院微信小程序反应问题不打也没全部患病,打3的照样传染,告知后果,就尊重意愿,顺8月份有部分退休人员的养老金被暂停发放了,这是怎么回事呢?无须担心,原因是这样的进入下半年以来,可能有的部分人员发现自己的养老金没有按时到位。经查询以后显示是被暂停发放,其实主要原因还是由于当事人没有进行领取养老金资格认证。领取养老金资格我外省户籍临近退休,在上海缴社保十四年半,能在上海办理退休吗?我外省户籍临近退休,在上海缴社保十四年半,能在上海办理退休吗?如果只在上海缴纳了14年半的养老保险,又没有在其他地方的缴费年限,这不管在哪里都是无法办理退休的,也包括上海市在内。达
放弃高薪执教机会,王治郅回归军旅拿月薪,军衔惊人,收入感人王治郅,中国男篮三大移动长城之一,虽然曾经有过一段不愉快经历,但他仍然为国家队立下了汗马功劳,2016年,王治郅正式宣布退役,他没有开启退休生活,而是转换身份继续为中国篮球的发展做签运有多重要?韩国队晋级,抽签撞大运,日本瑞典队眼红不已签运有多重要?有人欢喜有人忧。北京时间10月5日,成都世乒赛团体赛男子八分之一决赛中,首先是韩国对战波兰,30大比分顺利晋级。不少人调侃韩国队此次的签运真的是太好了,避开了死亡半区网曝多名双面人港星!杨千嬅被列为第一,吴镇宇被指脾气古怪双面人这个称谓听起来并不是很友善,但的的确确让人感到反感,尤其是在纷杂的娱乐圈中,人前人后两个模样,这样的艺人好像尤为多。早前,因为网友偶遇钟嘉欣,从而引发网友对她的负面评价,连带常吃发酵食品,或有助于减少体内炎症,医生建议6种食物可多吃在我们传承了几千年的饮食文化中,发酵食品是不可或缺的。自古以来,我们制作发酵食品的技术越来越成熟,制作出来的食品也越来越多样唯美,例如经常吃的酸奶泡菜各种发酵酒,都是发酵食品。食物常喝咖啡,到底好不好?医生这5类人最好不要碰,希望你能听劝说到咖啡,大家也并不陌生,咖啡从西方传入东方就成了小资品味的象征,与中国的茶一样,咖啡也是世界上比较受欢迎的饮料之一。但是在我们的日常生活中,许多人也对咖啡持怀疑态度,一些人认为长纹身师诉WWE2K侵权胜诉奥顿身上纹身未授权近日,纹身师凯瑟琳亚历山大诉2KSports及其母公司TakeTwo侵权案胜诉。凯瑟琳于2018年提起诉讼,声称她为摔跤巨星兰迪奥顿设计的纹身未经授权在WWE2K16WWE2K17退休医生表明多休息多运动对身体好,试着坚持2件小事或会长寿俗话说得好,生老病死人之常情,人的长度是有固定点的,而宽度没有大家可以通过有限的时间去做无限的事情。古代有很多王侯将相会追求长生不老,得永生,但没有一个人能成功,就连秦始皇也不例外台东海域,岛内与日本爆发冲突,三艘船对峙10个小时台媒日本舰船骚扰台船只对峙10小时文君剑近年来,台湾省的蔡当局为了讨好美国和日本,可以说是花样百出,各种献媚,甚至连莱猪(瘦肉精猪肉)和核食(日本核灾区食品)也都照单全收了。然而最修炼之开悟开悟。色即是空,空即是色,心无挂碍,这什么意思呢,各位,悟字是心和吾组合而成的,意思是用自己的心去领悟,色即是空,是让你把自己的心清空,清除一切杂念,杂思,什么也不要想,以一种空空情牵紫木槿有人说,爱上一个人,便爱上了他所在的一座城。而爱上一种花,不单单是因为这种花的美丽,更是因为这种花在你的生命中留下了芬芳的印记。很多时候,物是我们情感的载体。我对紫木槿情有独钟。木一夜秋雨感觉夏天的闷热刚刚褪去,转眼之间就到了九月。这个宁静的小山村秋天总是多雨的。田野里的玉米洋芋豆子等都开始收割了,也是一个收获的季节。此时这里便是多雨的天气,有时候雨会下上一周。辛劳