最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Quarkus中ConfigSourceInterceptor的加密配置實現(xiàn)

 更新時間:2022年02月23日 15:34:49   作者:kl  
這篇文章主要為大家介紹Quarkus中ConfigSourceInterceptor加密配置的實現(xiàn)方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

加密配置是一個很常見的需求,在spring boot生態(tài)中,已經(jīng)有非常多的第三方starter實現(xiàn)了,博主所在公司也有這種強(qiáng)制要求,一些敏感配置信息必須加密,比如第三方賬號,數(shù)據(jù)庫密碼等等。所以研究了下怎么在Quarkus中實現(xiàn)類似的配置加密功能。在前文 Quarkus集成apollo配置中心 中,已經(jīng)有介紹過Quarkus中的配置架構(gòu)了,配置加密功能也是基于smallrye-config來實現(xiàn)。

Eclipse MicroProfile Config:https://github.com/eclipse/microprofile-config/

smallrye-config:https://github.com/smallrye/smallrye-config

配置攔截器 ConfigSourceInterceptor

在實現(xiàn)功能前,先看下smallrye-config1.8版本新增的配置攔截器功能。ConfigSourceInterceptor攔截器定義如下:

public interface ConfigSourceInterceptor extends Serializable {
    ConfigValue getValue(ConfigSourceInterceptorContext context, String name);
  //省略、、、
}

實現(xiàn)這個接口,可以在配置加載的時候通過context拿到當(dāng)前配置的值,然后進(jìn)行任意邏輯操作。

攔截器是通過java.util.ServiceLoader機(jī)制加載的,可以通過提供名為io.smallrye.config.ConfigSourceInterceptor的文件進(jìn)行注冊,該資源META-INF/services/io.smallrye.config.ConfigSourceInterceptor包含完全限定的ConfigSourceInterceptor實現(xiàn)類名稱作為其內(nèi)容。

前文 Quarkus集成apollo配置中心 中,我們已了解Quarkus的配置基于Eclipse MicroProfile Config的規(guī)范和smallrye-config的實現(xiàn),但是ConfigSourceInterceptor的接口設(shè)計卻沒有包含在MicroProfile Config的配置規(guī)范中,smallrye團(tuán)隊正在努力參與規(guī)范的制定,所以后期這個接口很有可能會遷移到 MicroProfile Config包中,不過目前來看,你可以放心的使用smallrye-config1.8版本體驗配置攔截器功能

內(nèi)置的實現(xiàn)

smallrye-config內(nèi)置了如下配置攔截器實現(xiàn):

RelocateConfigSourceInterceptor

ProfileConfigSourceInterceptor

ExpressionConfigSourceInterceptor

FallbackConfigSourceInterceptor

LoggingConfigSourceInterceptor

SecretKeyConfigSourceInterceptor

默認(rèn)情況下,并非每個攔截器都已注冊。只有ProfileConfigSourceInterceptor, ExpressionConfigSourceInterceptor、SecretKeyConfigSourceInterceptor默認(rèn)已注冊。

其他攔截器需要通過ServiceLoader機(jī)制進(jìn)行手動注冊。配置中的${}表達(dá)式功能正是ExpressionConfigSourceInterceptor來實現(xiàn)的

加密配置實現(xiàn)

基于ConfigSourceInterceptor的機(jī)制,實現(xiàn)一個加密的攔截器,在配置時,標(biāo)記需要被解密的配置,在應(yīng)用啟動時,攔截配置加載,做解密處理即可。這里使用了AES加解密算法,將aesKey配置在配置文件中,將vi向量直接寫死在代碼里,這樣,即使別人拿到了你的完整配置,不知道vi向量值,也無法解密。

ConfigSourceInterceptor實現(xiàn)類可以通過標(biāo)準(zhǔn)javax.annotation.Priority 注釋指定優(yōu)先級。如果未明確指定優(yōu)先級,則采用io.smallrye.config.Priorities.APPLICATION默認(rèn)優(yōu)先級值 。指定優(yōu)先級時,value值越小,優(yōu)先級越高,這里指定為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 值越低優(yōu)先級越高
@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;
    /**
     * 需要加密值的前綴標(biāo)記
     */
    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,可增加加密算法的強(qiáng)度
           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加密函數(shù)
        * @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做轉(zhuǎn)碼。
           return Base64.getEncoder().encodeToString(encrypted);
       }
       /**
        * AES 解密函數(shù)
        *
        * @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)方法先得到加密的值,然后做如下配置,以數(shù)據(jù)庫密碼為例:

quarkus.datasource.username=mobile_office
quarkus.datasource.password=Encrypt=>/8wYwbxokEleEZzT4niJew==

使用Encrypt=>標(biāo)記了這個值是加密的,應(yīng)用程序加載時會被攔截到,然后做解密處理

結(jié)語

總的來說,Quarkus中使用的一些api設(shè)計是非常優(yōu)秀的的,通過預(yù)留的這種擴(kuò)展機(jī)制,可以非常輕松的實現(xiàn)擴(kuò)展功能。

以上就是Quarkus中ConfigSourceInterceptor的加密配置實現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Quarkus中ConfigSourceInterceptor加密的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談Java 中的引用類型

    淺談Java 中的引用類型

    Java開發(fā)者肯定都很熟悉java中的4種引用類型,它們從強(qiáng)到弱分別是:強(qiáng)引用、軟引用、弱引用和虛引用,下面我們詳細(xì)看看這些引用類型
    2020-02-02
  • Java java.lang.InstantiationException異常案例詳解

    Java java.lang.InstantiationException異常案例詳解

    這篇文章主要介紹了Java java.lang.InstantiationException異常案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 使用feign發(fā)送http請求解析報錯的問題

    使用feign發(fā)送http請求解析報錯的問題

    這篇文章主要介紹了使用feign發(fā)送http請求解析報錯的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java自定義函數(shù)調(diào)用方法解析

    Java自定義函數(shù)調(diào)用方法解析

    這篇文章主要介紹了java自定義函數(shù)調(diào)用方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Mybatis把返回結(jié)果封裝成map類型的實現(xiàn)

    Mybatis把返回結(jié)果封裝成map類型的實現(xiàn)

    本文主要介紹了Mybatis把返回結(jié)果封裝成map類型的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • SpringBoot-RestTemplate實現(xiàn)調(diào)用第三方API的方式

    SpringBoot-RestTemplate實現(xiàn)調(diào)用第三方API的方式

    RestTemplate?是由?Spring?提供的一個?HTTP?請求工具,它提供了常見的REST請求方案的模版,例如?GET?請求、POST?請求、PUT?請求、DELETE?請求以及一些通用的請求執(zhí)行方法?exchange?以及?execute,下面看下SpringBoot?RestTemplate調(diào)用第三方API的方式
    2022-12-12
  • sprintboot使用spring-security包,緩存內(nèi)存與redis共存方式

    sprintboot使用spring-security包,緩存內(nèi)存與redis共存方式

    這篇文章主要介紹了sprintboot使用spring-security包,緩存內(nèi)存與redis共存方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • JUnit5相關(guān)內(nèi)容簡介

    JUnit5相關(guān)內(nèi)容簡介

    這篇文章主要介紹了JUnit5相關(guān)內(nèi)容簡介,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • 將原生JDBC封裝實現(xiàn)CRUD的案例

    將原生JDBC封裝實現(xiàn)CRUD的案例

    這篇文章主要介紹了將原生JDBC封裝實現(xiàn)CRUD的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Java實現(xiàn)同步枚舉類數(shù)據(jù)到數(shù)據(jù)庫

    Java實現(xiàn)同步枚舉類數(shù)據(jù)到數(shù)據(jù)庫

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)同步枚舉類數(shù)據(jù)到數(shù)據(jù)庫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論

湟中县| 巴塘县| 沛县| 昭觉县| 教育| 陆丰市| 靖安县| 临湘市| 百色市| 西乌| 西青区| 锡林浩特市| 山西省| 襄汾县| 承德市| 天峨县| 滨海县| 朔州市| 大英县| 茌平县| 桐乡市| 蒲城县| SHOW| 长岛县| 尚义县| 墨江| 浦江县| 曲靖市| 龙州县| 临城县| 抚远县| 萍乡市| 岱山县| 五寨县| 贺兰县| 托克逊县| 永川市| 刚察县| 浦东新区| 北宁市| 澳门|