<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
加密設定是一個很常見的需求,在spring boot生態中,已經有非常多的第三方starter實現了,博主所在公司也有這種強制要求,一些敏感設定資訊必須加密,比如第三方賬號,資料庫密碼等等。所以研究了下怎麼在Quarkus中實現類似的設定加密功能。在前文 Quarkus整合apollo設定中心 中,已經有介紹過Quarkus中的設定架構了,設定加密功能也是基於smallrye-config來實現。
Eclipse MicroProfile Config:https://github.com/eclipse/microprofile-config/
smallrye-config:https://github.com/smallrye/smallrye-config
在實現功能前,先看下smallrye-config1.8版本新增的設定攔截器功能。ConfigSourceInterceptor攔截器定義如下:
public interface ConfigSourceInterceptor extends Serializable { ConfigValue getValue(ConfigSourceInterceptorContext context, String name); //省略、、、 }
實現這個介面,可以在設定載入的時候通過context拿到當前設定的值,然後進行任意邏輯操作。
攔截器是通過java.util.ServiceLoader機制載入的,可以通過提供名為io.smallrye.config.ConfigSourceInterceptor的檔案進行註冊,該資源META-INF/services/io.smallrye.config.ConfigSourceInterceptor包含完全限定的ConfigSourceInterceptor實現類名稱作為其內容。
前文 Quarkus整合apollo設定中心 中,我們已瞭解Quarkus的設定基於Eclipse MicroProfile Config的規範和smallrye-config的實現,但是ConfigSourceInterceptor的介面設計卻沒有包含在MicroProfile Config的設定規範中,smallrye團隊正在努力參與規範的制定,所以後期這個介面很有可能會遷移到 MicroProfile Config包中,不過目前來看,你可以放心的使用smallrye-config1.8版本體驗設定攔截器功能
smallrye-config內建瞭如下設定攔截器實現:
RelocateConfigSourceInterceptor
ProfileConfigSourceInterceptor
ExpressionConfigSourceInterceptor
FallbackConfigSourceInterceptor
LoggingConfigSourceInterceptor
SecretKeyConfigSourceInterceptor
預設情況下,並非每個攔截器都已註冊。只有ProfileConfigSourceInterceptor, ExpressionConfigSourceInterceptor、SecretKeyConfigSourceInterceptor預設已註冊。
其他攔截器需要通過ServiceLoader機制進行手動註冊。設定中的${}表示式功能正是ExpressionConfigSourceInterceptor來實現的
基於ConfigSourceInterceptor的機制,實現一個加密的攔截器,在設定時,標記需要被解密的設定,在應用啟動時,攔截設定載入,做解密處理即可。這裡使用了AES加解密演演算法,將aesKey設定在組態檔中,將vi向量直接寫死在程式碼裡,這樣,即使別人拿到了你的完整設定,不知道vi向量值,也無法解密。
ConfigSourceInterceptor實現類可以通過標準javax.annotation.Priority 註釋指定優先順序。如果未明確指定優先順序,則採用io.smallrye.config.Priorities.APPLICATION預設優先順序值 。指定優先順序時,value值越小,優先順序越高,這裡指定為PLATFORM早期攔截,程式碼如下:
/** * 1、使用方式為 正常設定值的前面拼接Encrypt=>字串,如 * quarkus.datasource.password = Encrypt=>xxxx * 2、設定解密的aeskey值,如 * config.encrypt.aeskey = 11111111111111111 * * @author kl : http://kailing.pub * @version 1.0 * @date 2020/7/10 9:46 */ //value 值越低優先順序越高 @Priority(value = Priorities.PLATFORM) public class EncryptConfigInterceptor implements ConfigSourceInterceptor { private static final String CONFIG_ENCRYPT_KEY = "config.encrypt.aeskey"; private static final int AES_KEY_LENGTH = 16; /** * 需要加密值的字首標記 */ private static final String ENCRYPT_PREFIX_NAME = "Encrypt=>"; /** * AES加密模式 */ private static final String AES_MODE = "AES/CBC/PKCS5Padding"; /** * AES的iv向量值 */ private static final String AES_IV = "1234567890123456"; @Override public ConfigValue getValue(ConfigSourceInterceptorContext context, String name) { ConfigValue config = context.proceed(name); if (config != null && config.getValue().startsWith(ENCRYPT_PREFIX_NAME)) { String encryptValue = config.getValue().replace(ENCRYPT_PREFIX_NAME, ""); String aesKey = context.proceed(CONFIG_ENCRYPT_KEY).getValue(); String value = AesEncyptUtil.decrypt(encryptValue, aesKey); return config.withValue(value); } return config; } public static void main(String[] args) { System.out.println("加密後的設定:"+ AesEncyptUtil.encrypt("office#123", "1111111111111111")); } static class AesEncyptUtil{ public static Cipher getCipher(int mode, String key) { if (key == null || key.length() != AES_KEY_LENGTH) { throw new RuntimeException("config.encrypt.key不能為空,且長度為16位元"); } SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES"); //使用CBC模式,需要一個向量iv,可增加加密演演算法的強度 IvParameterSpec iv = new IvParameterSpec(AES_IV.getBytes()); Cipher cipher = null; try { cipher = Cipher.getInstance(AES_MODE); cipher.init(mode, skeySpec, iv); } catch (InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | NoSuchAlgorithmException e) { e.printStackTrace(); } return cipher; } /** * AES加密函數 * @param plaintext 被加密的字串 * @param key AES key * @return 加密後的值 */ public static String encrypt(final Object plaintext, String key) { if (null == plaintext) { return null; } byte[] encrypted = new byte[0]; try { Cipher encryptCipher = getCipher(Cipher.ENCRYPT_MODE, key); encrypted = encryptCipher.doFinal(String.valueOf(plaintext).getBytes(StandardCharsets.UTF_8)); } catch (IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } //此處使用BASE64做轉碼。 return Base64.getEncoder().encodeToString(encrypted); } /** * AES 解密函數 * * @param ciphertext 被解密的字串 * @param key AES key * @return 解密後的值 */ public static String decrypt(final String ciphertext, String key) { if (null == ciphertext) { return null; } try { Cipher decryptCipher = getCipher(Cipher.DECRYPT_MODE, key); //先用base64解密 byte[] encrypted1 = Base64.getDecoder().decode(ciphertext); byte[] original = decryptCipher.doFinal(encrypted1); return new String(original, StandardCharsets.UTF_8); } catch (Exception ex) { ex.printStackTrace(); return null; } } } }
記得將完整的類名寫入到META-INF/services/io.smallrye.config.ConfigSourceInterceptor這個檔案中。使用時先設定好加密的key,在application.properties中新增如下設定:
config.encrypt.aeskey = xxxxxxxxxxxxxx
設定值一定要16位元,然後將需要加密的值,使用AesEncyptUtil.encrypt(final Object plaintext, String key)方法先得到加密的值,然後做如下設定,以資料庫密碼為例:
quarkus.datasource.username=mobile_office quarkus.datasource.password=Encrypt=>/8wYwbxokEleEZzT4niJew==
使用Encrypt=>標記了這個值是加密的,應用程式載入時會被攔截到,然後做解密處理
總的來說,Quarkus中使用的一些api設計是非常優秀的的,通過預留的這種擴充套件機制,可以非常輕鬆的實現擴充套件功能。
以上就是Quarkus中ConfigSourceInterceptor的加密設定實現的詳細內容,更多關於Quarkus中ConfigSourceInterceptor加密的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45