随着公司业务线不断壮大和发展,项目种类不断增多,对于配置的统一管理和监控以及支持动态发布等一些特性变成越来越重要的事情。所以需要引入配置中心进行与公司业务流程的适配。方向选型主要是Nacos和Apollo,二者区别这边不做赘述,最终落地选择了Apollo。在信息安全要求中,包含这么一条规则,要求放在配置中心的一些关键配置,比如数据库密码,各种中间件,MQ、以及服务器地址之类的数据,需要进行加密存储,以确保安全性。

Apollo本身是没有提供加解密的特性的,所以需要我们进行一些改造。

改造的方向有两点:1应用自身进行配置解密的动作 2在Apollo-client统一实现。

基于第一点,我在springboot和Mvc项目中都分别做了实现,但是业务代码耦合相对比较严重,并且加解密的动作最好还是做一个统一的地方处理,符合一种服务化的思想。

所以基于第二点,做了如下探索和改造。

其实网络上可以搜索到对应的一些改造方式,不亚于就是在DefaultConfig的updateConfig方法中添加上自己的解密逻辑。

那么为什么要在这个地方加上解密的逻辑呢?

其实很简单,这个类是Apollo启动流程中默认注入的类,并且在两个地方有所调用

其一:初始化的时候调用

其二:远程配置中心有变更监听到配置变更消息的时候调用

所以我们在这个方法中加入解密逻辑是没有问题的。我本地也进行了对应的测试实现。

但是做完之后我们思考一个逻辑,我们在引入一个框架解决某些问题的时候,本质上应该本着不去修改它源代码的角度上去进行扩展功能的实现,这样有利于我们后期做一些框架升级的动作,因为无论随着公司人员流转调动或者历史因素,总会有一些代码是没有人维护的,所以我们应该将后期的升级成本尽可能的缩小。所以这时候基于这样的思考点,我们应该想想能不能自己基于Apollo-client做一层封装,去实现加解密的功能呢?答案自然是可以的。

这时候我们应该从研究一个客户端在启动并且调用Apollo-client获取配置的流程性上去考虑。

基于这种流程,我们在IDE工具中进行对应的debug调试和源码跟踪,其实可以比较方便的跟踪到各个调用类。Apollo源码中提供了很多demo类给我们进行测试,这边不做过多赘述。

 

我们可以看出来,从我的ApolloConfigDemo,会调用到ConfigService中,然后再调用到DefaultConfigManager中去。这是在我的 ApolloConfigDemo的调用逻辑,那么平时我们Apollo接入spring的时候,也是走这样的逻辑吗?我们可以验证一下:

这边我直接说结论,最终Apollo利用了spring框架特性,在initializePropertySources方法里一样会走ConfigService的调用逻辑。

所以这时候对于ConfigService的调用逻辑的研究就显得尤为重要了。

从ConfigService.getConfig()方法中我们可以观察到这样一行代码

s_instance就是ConfigService对象.它调用了getManager()中

在这个方法我们可以看到这样的代码:

他通过了ApolloInjector,对configManager的实现类实现了注入并且赋值到了m_configManager变量上。到这里我们可能还没什么逻辑。但是我们从调用链路继续往下走,会发现ApolloInjector在各个地方都进行了接口实现类的调用。

所以这时候我们可以先猜测一下,ApolloInjector这个类的作用,应该是约定和绑定了初始化的时候应该加载什么类型的ConfigManager、ConfigFactoryManager、ConfigFactory 的实现类。所以这时候我们可以开始研究一下ApolloInjector这个类了。

当我们点进去之后我们看到这样的代码:

ServiceBootstrap是Apollo自己做的一层封装,有点类加载器的味道。点进去之后我们可以看到
他的loadFirst方法只会加载第一个实例。并且我们看到这样一个有趣的异常信息:
"No implementation defined in /META-INF/services/%s, please check whether the file exists and has the right implementation class!",

很明显,这是一个SPI机制注入的东西。那么我们去看看它SPI注入了什么类。(不懂SPI是什么的朋友可以自己先做一些了解和学习)

对于这个接口,他其实默认使用SPI注入了DefaultInjector,再对DefaultInjector做了一层封装,包装在了ApolloInjector中去调用,其实最后还是会走到DefaultInjector的逻辑中。那么DefaultInjector又做了哪些事呢?

我们可以看到,它在初始化的时候调用了ApolloModule(),去初始化了ApolloModule这个类。而ApolloModule这个类是做什么用的?

到这边就一目了然了,Apollo利用了SPI注入了DefaultConfig,然后又初始化了一个静态的内部类ApolloModule,这个类定义和封装好了Apollo之后在client启动链路上需要使用到的各个组件的默认实现。

所以了解到这里,已经差不多了。很明显,我们想要的改造是DefaultConfig。那么我们需要怎么改?

第一:我们在ide中新建一个module,封装Apollo-client组件。

第二:在我们的module中,我们写一个自己的Injector类,去替换掉默认的DefaultInjector.我们也一样的使用SPI机制注入进去,因为Apollo默认只会拿第一个,所以一定会拿到我们自己module中的实现类。自己的Injector类可以直接将DefaultInjector拷贝过来。

第三:在调用链路上,真正调用到DefaultConfig的类其实是DefaultConfigFactory

所以我们重写 DefaultConfigFactory以及DefaultConfig,将我们自己重写的DefaultConfigFactory调用到我们自己重写的DefaultConfig,并且在我们自己重写的DefaultConfig中的updateConfig()方法实现解密的逻辑即可。

最后,我们需要在第一步我们自己的Injector类中,将DefaultConfigFactory替换成我们自己的ConfigFactory,就能够实现解密的动作了。

主要实现的东西就这么几个

最后我们可以进行一些测试:

 在我改造的代码中我做了如下打印,将获取到加密的值打印出来,并且将解密的值也打印出来

 最终在启动的时候可以看到如下打印信息:

成功解密.

最后,附上我的改造的module代码地址:

apoll-hm-demo: 基于Apollo-client进行的加解密扩展https://gitee.com/biggerHuang_min/apoll-hm-demo

Apollo配置加解密-基于Apollo—client的封装支持配置动态解密的巧思与探索相关推荐

  1. @scheduled注解配置时间_Java开发重写Spring Boot定时任务,支持可动态调整执行时间...

    Spring Boot应该是目前最火的java开源框架了,它简化了我们创建一个web服务的过程,让我们可以在很短时间.基本零配置就可以启动一个web服务. 定时任务在我们平常的业务开发用的非常多,Sp ...

  2. Vue 2.x折腾记 - (17) 基于Ant Design Vue 封装一个配置式的表单组件

    前言 写了个类似上篇搜索的封装,但是要考虑的东西更多. 具体业务比展示的代码要复杂,篇幅太长就不引入了. 效果图 2019-04-25 添加了下拉多选的渲染,并搜索默认过滤文本而非值 简化了渲染的子组 ...

  3. Vue 2.x折腾记 - (16) 基于Ant Design Vue 封装一个配置式的表单搜索组件

    前言 这次的后台管理系统项目选型用了Vue来作为主技术栈: 因为前段时间用过React来写过项目(用了antd),感觉棒棒的. 所以这次就排除了Element UI,而采用了Ant Design Vu ...

  4. Nginx配置及配置加载

    Nginx配置(Directives) Nginx默认配置 worker_processes 1;events {worker_connections 1024; }http {include mim ...

  5. 基于apollo实现配置灰度发布

    前言 在上一篇,通过dubbo的版本号控制,我们实现了一个服务的简单的灰度发布过程,在真实的项目环境中,灰度发布的应用场景是很多的,服务接口存在灰度的需求,本篇再介绍另一种比较常见的灰度需求场景,即配 ...

  6. apollo配置mysql_携程apollo配置中心搭建

    服务jar包及初始化数据库脚本下载:(包括单机快速部署版本.加密版本.非加密版本) 云盘的Apollo是在原官方1.3版本基础上做过二次开发,请务必通过云盘链接下载相应的zip包. Apollo统一使 ...

  7. 聊一聊.NET Core结合Nacos实现配置加解密

    背景 当我们把应用的配置都放到配置中心后,很多人会想到这样一个问题,配置里面有敏感的信息要怎么处理呢? 信息既然敏感的话,那么加个密就好了嘛,相信大部分人的第一感觉都是这个,确实这个是最简单也是最合适 ...

  8. Apollo通过客户端openApi方式更新、获取、发布配置

    pom <!--apollo 配置依赖--><dependency><groupId>com.ctrip.framework.apollo</groupId& ...

  9. laravel配置加解密

    基于安全考虑,我们php项目配置文件中密码应该是加密的,laravel中也提供了OpenSSL 的 AES-256-CBC 来进行加密 但是如果我们项目配置的是其他加密方式,且希望以最少的改动实现读取 ...

最新文章

  1. elasticsearch资源汇总
  2. python 查看当前目录_「Python」打包分发工具setuptools学习
  3. 300来行代码实现最小Linux文件系统
  4. Firefox扩展批量安装脚本
  5. python降维可视化 自编码_如何使用自动编码器可视化降维? (Python | TensorFlow)...
  6. 解决Winform应用程序中窗体背景闪烁的问题
  7. 《玩转Django2.0》读书笔记-编写URL规则
  8. IT桌面运维常识系列 - MDT
  9. DWM1000模块简介
  10. Linux应用层24点小游戏,C++ Builder构建算二十四点小游戏
  11. 微信公众号开发诡异问题:errcode:40125,errmsg解决方案
  12. 服务器正常运行温度,服务器cpu的温度在什么范围内是属于正常温度
  13. php日期自动加一天,php 当前日期加一天和指定日期加一天
  14. cocos2d-x 3.2 之 三消类游戏——万圣大作战
  15. SVA序列表达式操作符(intersect、within、throughout、first_match、matched)
  16. mysql slave 1062_mysql主从同步slave错误1062
  17. php对接WPS开放平台word编辑demo
  18. 关于阿里云ACP认证的那些事儿
  19. 有哪些可以快速回复信息的软件
  20. 实习报告大盘点 【建议收藏】

热门文章

  1. 说说Android桌面(Launcher应用)背后的故事(七)——又是一个附属品(可以转动的绚烂饼图)
  2. 搅拌站ERP管理系统-砼友ERP
  3. 你写的代码就是你的犯罪证据
  4. 设计分享|单片机抢答器(汇编)
  5. 前端工程师掌握这18招,就能在浏览器里玩转深度学习
  6. heaviside()
  7. 如何测量电源的噪声(有视频)
  8. birt java_BIRT的Java实现
  9. 【MongoDB入门】
  10. 更快更强大,Oracle Primavera P6 R18.8 发布