jasypt 3.0.4 Bug 分析与解决

背景

目前项目中使用 jasypt 来做配置项的加解密,但是在实际使用中发现 3.0.4 版本中 ,在配置中心动态刷新后,@ConfigurationProperties 的属性全部变成加密数据(如 ENC(XXX=)

接下来是源码和部分机制原理分析,如果关心解决方法的话,可以快进到 “解决思路” 章节

jasypt 原理分析

Spring 框架中,所有的配置数据都存储在 PropertySource 中,我们经常在 Spring 框架中使用 Environment 来读取配置数据。Environment 内部包含多个 PropertySource(例如 bootstrap.yml 和 application.yml 会被解析为两个独立的 PropertySource)。当调用 Environment.getProperty 时,其内部会遍历所有的 PropertySource,最终通过 PropertySource.getProperty 来寻找指定配置。

所以 jasypt 的核心思路就是代理(或者说包装)所有的 PropertySource

jasypt 使用 EnableEncryptablePropertiesBeanFactoryPostProcessor 在Bean 初始化之前代理所有 PropertySource。代理后的类我们用 EncryptablePropertySource 来同一称呼。

EnableEncryptablePropertiesBeanFactoryPostProcessor

EncryptablePropertySource.getProperty 实现逻辑大致如下:当读取到配置后,如果 value 的格式是 ENC(xxx),将会调用解密方法对加密数据进行解密

用伪代码和图总结下上面的文字

小结

Spring Cloud 动态刷新配置机制分析

Spring Cloud 为标记 @ConfigurationProperties 的类提供了动态刷新的功能。文档:https://cloud.spring.io/spring-cloud-static/spring-cloud.html#_environment_changes

这里我的配置中心是 Nacos(任何配置中心都可以通过发布事件或者调用 Spring Cloud endpoint 的方式来刷新配置)

当 Nacos 监听到配置文件更新时,会发布 RefreshEvent。发布事件后,代码会执行到 ContextRefresher,该类主要作用是通过创建一个新的 Spring Context 初始化(为了加载新的配置),然后发送 EnvironmentChangeEvent

ContextRefresher

当执行完 93 行时,最新的配置已经加载完毕。其实创建新的 Spring Context 也会执行到 EnableEncryptablePropertiesBeanFactoryPostProcessor 逻辑,但是由于加载顺序的原因,生成代理类之前并没有加载 Nacos 的配置。

但是 jasypt 提供了一个 RefreshScopeRefreshedEventListener,该类监听了 RefreshScopeRefreshedEvent, EnvironmentChangeEvent, ServletWebServerInitializedEvent 提供了和 EnableEncryptablePropertiesBeanFactoryPostProcessor 类似的逻辑,将 PropertySource 转换(代理)为 EncryptablePropertySource

RefreshScopeRefreshedEventListener

问题发现

但是此时发现 PropertySource 可以被成功代理,但是配置密文却无法解密,一番 debug 之后发现,执行 @ConfigurationProperties 绑定的类 ConfigurationPropertiesRebinder 先于 RefreshScopeRefreshedEventListener 执行。

所以现在此时的问题就是如何调整 RefreshScopeRefreshedEventListener 的执行顺序。

这时我发现了 RefreshScopeRefreshedEventListener 使用了 @Order 注解并且实现了 Ordered 接口

RefreshScopeRefreshedEventListener @Order
RefreshScopeRefreshedEventListener getOrder

但是发现两个顺序并不一致(应该是作者的疏忽),并且在实际代码运行中,注解并不生效,这里我尝试将 getOrder 顺序修改为与直接一致,然后重新调试,发现问题已经解决。

解决方案

  1. 调整 RefreshScopeRefreshedEventListener 顺序,保证该类执行顺序先于 ConfigurationPropertiesRebinder

    可以选择将顺序调为 HIGHEST_PRECEDENCE,也可以选择仅优先于 RefreshScopeRefreshedEventListener ,不影响其他 Listener

  2. 参考 EnvironmentDecryptApplicationInitializer,使用 ApplicationContextInitializer 实现对 PropertySource 的代理。

    在编写本文时,发现 Spring Cloud 提供了类似 jasypt 的加解密方案,通过 debug 发现 EnvironmentDecryptApplicationInitializer 的执行时机要比 jasypt 更合适(不需要像 jasypt 一样写两个类处理),更多细节读者自行阅读 EnvironmentDecryptApplicationInitializer 源码

@Value 动态更新

@Value 方式动态更新并不会受到影响,因为本质上 @Value 和 @ConfigurationProperties 的刷新机制不同


更新于 2023 年 2 月 1 日,我的 PR 已经被作者 merge,用户升级到 3.0.5 即可
https://github.com/ulisesbocchio/jasypt-spring-boot/pull/344

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容