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

jasypt-spring-boot-starter實(shí)現(xiàn)加解密和數(shù)據(jù)返顯方式

 更新時(shí)間:2025年05月21日 10:04:34   作者:神雕大俠mu  
這篇文章主要介紹了jasypt-spring-boot-starter實(shí)現(xiàn)加解密和數(shù)據(jù)返顯方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

jasypt-spring-boot-starter實(shí)現(xiàn)加解密和數(shù)據(jù)返顯

一、青銅:jasypt-spring-boot-starter在springboot中的加解密(默認(rèn)加密法)

1、導(dǎo)包

  <!--實(shí)現(xiàn)自動(dòng) 加密解密-->
        <dependency>
            <groupId>com.github.ulisesbocchio</groupId>
            <artifactId>jasypt-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

注意這里引入的版本號(hào),2.x和3.x會(huì)有差別,后面會(huì)講

2、配置yml

  • 2.1、關(guān)于jasypt部分的配置:
jasypt:
  encryptor:
  	#加解密的密碼
    password: atpingan
    #jasypt默認(rèn)更改了算法,如果不指定那么會(huì)報(bào)錯(cuò):failed to bind properties under 'spring.datasource.druid.password' to java.lang.String
    #解決辦法:①把版本降到2.x②指定加密方法,如下
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator
  • 2.2、關(guān)于加密部分的配置:
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://192.168.200.141:3306/mysql?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
      #加密密碼atpingan,ENC() 是默認(rèn)加解密的標(biāo)識(shí)
      username: ENC(kud5ZnaMJYve284geT0ITw==)
      password: ENC(0CwfH4246HP22Rv74d/ZPw==)

其中ENC()是默認(rèn)加密法的固定配置,后面會(huì)講自定義加密法

  • 2.3、重點(diǎn):(2.x和3.x的區(qū)別)

jasypt默認(rèn)更改了算法,如果不指定那么會(huì)報(bào)錯(cuò):

failed to bind properties under spring.datasource.druid.password' to java.lang.String

#解決辦法:

  • ①把版本降到2.x
  • ②指定加密方法,如下
jasypt:
  encryptor:
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator
    password: atpingan

3、計(jì)算ENC()中的內(nèi)容

上面你是否疑惑ENC(kud5ZnaMJYve284geT0ITw==)中的內(nèi)容是怎么來(lái)的?

他是根據(jù):

jasypt:
  encryptor:
  	#加解密的密碼
    password: atpingan

的密碼來(lái)計(jì)算出來(lái)的。自己建一個(gè)main方法類,計(jì)算出來(lái)即可,計(jì)算完這個(gè)類就沒(méi)用了,可以刪除。

 public static void main(String[] args) {
 
        BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
        textEncryptor.setPassword("atpingan");
        
        String userName = textEncryptor.encrypt("root");
        String passWord = textEncryptor.encrypt("123456");
        
        System.out.println("userName==="+userName);
        System.out.println("passWord==="+passWord);
      
    }

4、添加注解

在啟動(dòng)類上添加注解 @EnableEncryptableProperties

啟動(dòng)項(xiàng)目,發(fā)現(xiàn)正常,那就是對(duì)數(shù)據(jù)庫(kù)的賬號(hào)密碼實(shí)現(xiàn)了加密

二、黃金:自定義加密、解密及前綴后綴方法

1、導(dǎo)包(只列出最主要的包,其他相關(guān)的包不一一列舉)

  <!--實(shí)現(xiàn)自動(dòng) 加密解密-->
        <dependency>
            <groupId>com.github.ulisesbocchio</groupId>
            <artifactId>jasypt-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

2、寫(xiě)配置類(重點(diǎn))

springboot中的條件注解匯總

注解作用
@Conditional判斷是否滿足當(dāng)前指定條件
@ConditionalOnJava系統(tǒng)的java版本是否符合要求
@ConditionalOnBean容器中存在指定Bean才執(zhí)行
@ConditionalOnMissingBean容器中不存在指定Bean才執(zhí)行
@ConditionalOnExpression滿足SpEL表達(dá)式指定
@ConditionalOnClass系統(tǒng)中有指定的類
@ConditionalOnMissingClass系統(tǒng)中沒(méi)有指定的類
@ConditionalOnSingleCandidate容器中只有一個(gè)指定的Bean,或者這個(gè)Bean是首選Bean
@ConditionalOnProperty系統(tǒng)中指定的屬性是否有指定的值
@ConditionalOnResource類路徑下是否存在指定資源文件
@ConditionalOnWebApplication當(dāng)前是web環(huán)境
@ConditionalOnNotWebApplication當(dāng)前不是web環(huán)境
@ConditionalOnJndiJNDI存在指定項(xiàng)

2.1、啟動(dòng)加載的配置類JasyptConfiguration ,即入口。

@Configuration
public class JasyptConfiguration {
	//這里的名字必須是jasyptStringEncryptor,不能改動(dòng)
    @Bean(name = "jasyptStringEncryptor")
    @ConditionalOnMissingBean
    public StringEncryptor stringEncryptor(MyEncryptablePropertyDetector propertyDetector){
        return new DefaultEncryptor(propertyDetector);
    }
    //這里的名字必須是encryptablePropertyDetector,不能改動(dòng)
    @Bean(name = "encryptablePropertyDetector")
    @ConditionalOnMissingBean
    public MyEncryptablePropertyDetector encryptablePropertyDetector() {
        return new MyEncryptablePropertyDetector();
    }
}

2.2、監(jiān)聽(tīng)類,它會(huì)找到配置文件中包含指定前后綴的數(shù)據(jù),如這里指定的 ikms( 和 )

public class MyEncryptablePropertyDetector implements EncryptablePropertyDetector {
    private String prefix = "ikms(";
    private String suffix = ")";
    public MyEncryptablePropertyDetector() {
    }
    public MyEncryptablePropertyDetector(String prefix, String suffix) {
        Assert.notNull(prefix, "Prefix can't be Null");
        Assert.notNull(suffix, "Suffix can't be Null");
        this.prefix = prefix;
        this.suffix = suffix;
    }
    /**
    *判斷配置文件中的數(shù)據(jù)是否是按這里指定前后綴組裝的
    **/
    @Override
    public boolean isEncrypted(String message) {
        if (StringUtils.isBlank(message)) {
            return false;
        } else {
            String trimmedValue = message.trim();
            return trimmedValue.startsWith(this.prefix) && trimmedValue.endsWith(this.suffix);
        }
    }
    @Override
    public String unwrapEncryptedValue(String message) {
        /**
         *獲取到 上面方法返回true的數(shù)據(jù)
         * 此處原數(shù)據(jù)返回,不作處理,統(tǒng)一在DefaultEncryptor處理
         */
        return message;
    }
    public String getPrefix() {
        return prefix;
    }
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
    public String getSuffix() {
        return suffix;
    }
    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}

2.3、實(shí)現(xiàn)凱撒解密并把數(shù)據(jù)返顯回配置文件

public class DefaultEncryptor implements StringEncryptor {
	/**
	*獲取寫(xiě)在配置文件中的參數(shù),這里是解密的密碼
	**/
    @Value("${jasypt.encryptor.password}")
    private int decryptPassword;

    private MyEncryptablePropertyDetector propertyDetector;
    public DefaultEncryptor() {
    }
    public DefaultEncryptor( MyEncryptablePropertyDetector propertyDetector) {
        this.propertyDetector = propertyDetector;
    }
    /**
    *這里是加密方法,我們不在這里加密,原參數(shù)返回
    **/
    @Override
    public String encrypt(String encryptMessage) {
        return  encryptMessage ;
    }
    /**
    *凱撒解密
    **/
    @Override
    public String decrypt(String decryptMessage) {
        /**
         * 從MyEncryptablePropertyDetector的 unwrapEncryptedValue方法返回的數(shù)據(jù)在這里處理
         */
        String prefix = propertyDetector.getPrefix();
        String suffix = propertyDetector.getSuffix();
        int prefixIndex = decryptMessage.indexOf(prefix);
        int suffixIndex = decryptMessage.indexOf(suffix);
        /**
         * 截取括號(hào)中間部分,例如:ikms(鄰居小玲) 里面的:鄰居小玲
         */
        decryptMessage = decryptMessage.substring(prefixIndex+prefix.length(),suffixIndex);
        /**
         * 做凱撒解密:加解密公共方法,請(qǐng)往后看
         */
        String result = KaiserUtil.decryptKaiser(decryptMessage,decryptPassword);
        return result;
    }
}

2.4、凱撒加解密的公共方法

public class KaiserUtil {

    public static void main(String[] args) {
        String encryptKaiser = encryptKaiser("root",123456789);
        String decryptKaiser = decryptKaiser(encryptKaiser, 123456789);
        System.out.println("encryptKaiser==="+encryptKaiser);
        System.out.println("decryptKaiser==="+decryptKaiser);
    }

    /**
     * 使用凱撒加密方式加密數(shù)據(jù)
     * @param orignal :原文
     * @param key     :密鑰
     * @return :加密后的數(shù)據(jù)
     */
    public static String encryptKaiser(String orignal, int key) {
        // 將字符串轉(zhuǎn)為字符數(shù)組
        char[] chars = orignal.toCharArray();
        StringBuilder sb = new StringBuilder();
        // 遍歷數(shù)組
        for (char aChar : chars) {
            // 獲取字符的ASCII編碼
            int asciiCode = aChar;
            // 偏移數(shù)據(jù)
            asciiCode += key;
            // 將偏移后的數(shù)據(jù)轉(zhuǎn)為字符
            char result = (char) asciiCode;
            // 拼接數(shù)據(jù)
            sb.append(result);
        }
      
        return sb.toString();
    }
    /**
     * 使用凱撒加密方式解密數(shù)據(jù)
     * @param encryptedData :密文
     * @param key           :密鑰
     * @return : 源數(shù)據(jù)
     */
    public static String decryptKaiser(String encryptedData, int key) {
        // 將字符串轉(zhuǎn)為字符數(shù)組
        char[] chars = encryptedData.toCharArray();
        StringBuilder sb = new StringBuilder();
        // 遍歷數(shù)組
        for (char aChar : chars) {
            // 獲取字符的ASCII編碼
            int asciiCode = aChar;
            // 偏移數(shù)據(jù)
            asciiCode -= key;
            // 將偏移后的數(shù)據(jù)轉(zhuǎn)為字符
            char result = (char) asciiCode;
            // 拼接數(shù)據(jù)
            sb.append(result);
        }
        return sb.toString();
    }
}

3、寫(xiě)配置文件

3.1、配置jasypt密鑰及指定加解密方法

jasypt:
  encryptor:
    #解密的密鑰
    password: 123456789
    #jasypt 3.x版本默認(rèn)更改了算法,如果不指定那么會(huì)報(bào)錯(cuò):failed to bind properties under 'spring.datasource.druid.password' to java.lang.String
    #解決辦法:①把版本降到2.x ②指定加密方法,如下
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator

注意:

  • 這里的algorithmiv-generator-classname可以不要,因?yàn)槲覀冎貙?xiě)了解密方法,不用它本身的加解密方法。
  • 寫(xiě)上也不會(huì)報(bào)錯(cuò),用不上。我留下它們主要是想說(shuō)明版本差異造成的報(bào)錯(cuò)及解決辦法

3.2、數(shù)據(jù)庫(kù)的連接配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://192.168.200.141:3306/mysql?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
      #加密密碼atpingan
      #username: root
      #password: 420188
      username: ikms(????)
      password: ikms(??????)

至此就寫(xiě)完了自定義jasypt的加解密,這種方法也不需要加@EnableEncryptableProperties,因?yàn)榧虞d的是我們自定義加解密方法

三、王者:使用jasypt做一個(gè)starter

最近遇到一個(gè)業(yè)務(wù)需求,要把數(shù)據(jù)庫(kù)、redis、es等等的密碼都從kms的密碼保管箱中獲取,場(chǎng)景是項(xiàng)目啟動(dòng)就獲取并加載到配置文件中,java代碼只需通過(guò)@Value去取,實(shí)現(xiàn)方法是自定義一個(gè)starter,并使用jasypt,不需要它的加解密功能,只要返顯數(shù)據(jù)到配置文件即可。

我的文件目錄結(jié)構(gòu)是:

1、定義starter的啟動(dòng)加載文件spring.factories

下載resource/META-INF下面:(它是starter的入口)

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.pingan.idaas.datadecryptbootautoconfigure.jasypt.JasyptConfiguration

2、寫(xiě)jasypt的文件

2.1、配置類,spring.factories加載的就是這個(gè)類

@Configuration
@EnableConfigurationProperties(DataDeCryptProperties.class)
public class JasyptConfiguration {
    @Bean
    @ConditionalOnMissingBean(DataDecryptService.class)
    public DataDecryptService dataDecryptService(DataDeCryptProperties dataDeCryptProperties){
        return new DataDecryptService(dataDeCryptProperties);
    }
    @Bean(name="encryptablePropertyDetector")
    @ConditionalOnMissingBean
    public MyEncryptablePropertyDetector encryptablePropertyDetector(){
        return new MyEncryptablePropertyDetector();
    }
    // 注意這里,因?yàn)樗卸鄠€(gè)實(shí)現(xiàn)類,其他實(shí)現(xiàn)類實(shí)例化后有可能導(dǎo)致,此處不實(shí)例化,所以這里要用@Primary標(biāo)注
    @Bean(name = "jasyptStringEncryptor")
    @Primary
    public StringEncryptor stringEncryptor(DataDecryptService dataDecryptService,MyEncryptablePropertyDetector myEncryptablePropertyDetector){
        return new DefaultEncryptor(dataDecryptService,myEncryptablePropertyDetector);
    }
}

2.2、獲取配置文件參數(shù)并判斷出指定前后綴的是哪些

public class MyEncryptablePropertyDetector implements EncryptablePropertyDetector {
    private String prefix = "AIDSREN(";
    private String suffix = ")";
    public MyEncryptablePropertyDetector() {

    }
    public MyEncryptablePropertyDetector(String prefix, String suffix) {
        this.prefix = prefix;
        this.suffix = suffix;
    }
    @Override
    public boolean isEncrypted(String message) {
        if(StringUtils.isBlank(message)){
            return false;
        }
        String trimValue = message.trim();
        return trimValue.startsWith(this.prefix) && trimValue.endsWith(this.suffix);
    }
    @Override
    public String unwrapEncryptedValue(String message) {
        return message;
    }
    public String getPrefix() {
        return prefix;
    }
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
    public String getSuffix() {
        return suffix;
    }
    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}

2.3、這里本來(lái)是加解密的類,但是我們根據(jù)業(yè)務(wù)需求,這里不做加解密,做業(yè)務(wù)邏輯,并返顯數(shù)據(jù)到配置文件參數(shù)中

public class DefaultEncryptor implements StringEncryptor {

    private static final Log log = LogFactory.getLog(DefaultEncryptor.class);

    private DataDecryptService dataDecryptService;
    private MyEncryptablePropertyDetector propertyDetector;
    @Autowired
    private DataDeCryptProperties dataDeCryptProperties;
    private String innerPrefix = "AEN(";
    private String innerSuffix = ")";
    public static final String COLON = "::";

    public DefaultEncryptor() {

    }
    public DefaultEncryptor(DataDecryptService dataDecryptService, MyEncryptablePropertyDetector propertyDetector) {
        this.dataDecryptService = dataDecryptService;
        this.propertyDetector = propertyDetector;
    }
    public DefaultEncryptor(MyEncryptablePropertyDetector propertyDetector) {

        this.propertyDetector = propertyDetector;
    }
    @Override
    public String encrypt(String message) {
        return message;
    }
    /**
     * 解密
     * @param message
     * @return
     */
    @Override
    public String decrypt(String message) {
        String prefix = propertyDetector.getPrefix();
        String suffix = propertyDetector.getSuffix();
        message = CommonTool.getMessage(message, prefix, suffix);
        String result = "";
        if (StringUtils.isNotBlank(message)) {
            result = getDecryptOrRemoteKey(message);
        }
        return result;
    }
    /**
     * 獲取含有 :: 的個(gè)數(shù)并分支
     * @param message
     * @return
     */
    private String getDecryptOrRemoteKey(String message) {
        int countOfColon = countColon(message);
        if (countOfColon <= 0) {
            return getResultWithNoColon(message);
        }
        if (countOfColon == 1) {
            return getResultWithColon(message);
        }
        return "";
    }
    /**
     * 未含有 :: 的處理邏輯
     * @param message
     * @return
     */
    private String getResultWithNoColon(String message) {
        String trimValue = message.trim();
       boolean flag = trimValue.startsWith(innerPrefix) && trimValue.endsWith(innerSuffix);
       if(flag){
           int decryptPassword = dataDeCryptProperties.getDecryptPassword();
           message = CommonTool.getMessage(message, innerPrefix, innerSuffix);
           return IdaasKaiserUtil.decryptKaiser(message,decryptPassword);
       }
       return message;
    }
    /**
     * 含有一個(gè) :: 的處理邏輯
     * @param message
     * @return
     */
    private String getResultWithColon(String message) {
        String result = null;
        String[] messageArray = message.split(COLON);
        String key = messageArray[0];
        String value = messageArray[1];
        String url = dataDeCryptProperties.getUrl();
        result = getByRemoteOrKms(key, url);
        if (StringUtils.isBlank(result)) {
            result = getResultWithNoColon(value);
        }
        return result;
    }
    /**
     * 遠(yuǎn)程獲取密鑰
     * @param key
     * @param url
     * @return
     */
    private String getByRemoteOrKms(String key, String url) {
        CustomGetCryptorService cryptorService = getCryptorInstance();

        try {
            return cryptorService.getRemoteCryptor(url, key);
        } catch (Exception e) {
            log.error("獲取遠(yuǎn)程密鑰失敗", e);
        }
        return null;
    }
    /**
     * 獲取對(duì)象(starter本身密鑰獲取對(duì)象 還是 客戶端自定義密鑰獲取對(duì)象)
     * @return
     */
    private CustomGetCryptorService getCryptorInstance() {
        String customGetCryptorClass = dataDeCryptProperties.getCustomGetCryptorClass();
        CustomGetCryptorService customGetCryptorService = null;
        try {
            if (StringUtils.isNotBlank(customGetCryptorClass)) {
                Class<?> clazz = Class.forName(customGetCryptorClass);
                customGetCryptorService = (CustomGetCryptorService) clazz.newInstance();
            } else {
                customGetCryptorService = new CustomGetCryptorServiceImpl();
            }
        } catch (Exception e) {
            log.error("獲取客戶端對(duì)象失??!");
        }
        return customGetCryptorService;
    }
    /**
     * 計(jì)算::的個(gè)數(shù)
     * @param message
     * @return
     */
    private int countColon(String message) {
        String trimValue = message.trim();
        int count = 0;
        int length = message.length();
        while (trimValue.indexOf(COLON) != -1) {
            trimValue = trimValue.substring(trimValue.indexOf(COLON) + 1, length);
            count++;
        }
        return count;
    }
}

3、寫(xiě)屬性類和業(yè)務(wù)類

3.1、屬性類HelloProperties即是獲取調(diào)用本starter的yml(或properties)中的指定前綴的數(shù)據(jù)內(nèi)容

這里指定要獲取前綴為atguigu.hello開(kāi)頭的參數(shù)

@ConfigurationProperties(prefix = "idaas.decerypt")
public class DataDeCryptProperties {

    private String url;
    private int decryptPassword;
    private String customGetCryptorClass;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public int getDecryptPassword() {
        return decryptPassword;
    }
    public void setDecryptPassword(int decryptPassword) {
        this.decryptPassword = decryptPassword;
    }
    public String getCustomGetCryptorClass() {
        return customGetCryptorClass;
    }
    public void setCustomGetCryptorClass(String customGetCryptorClass) {
        this.customGetCryptorClass = customGetCryptorClass;
    }
}

3.2、獲取業(yè)務(wù)類

此處僅僅是擺設(shè)未實(shí)際用到

public class DataDecryptService {

    private DataDeCryptProperties dataDeCryptProperties;
    public DataDecryptService() {

    }
    public DataDecryptService(DataDeCryptProperties dataDeCryptProperties) {
        this.dataDeCryptProperties = dataDeCryptProperties;
    }
}

遠(yuǎn)程獲取密鑰口子:

接口:

public interface CustomGetCryptorService {
    String getRemoteCryptor(String url, String key);
}

實(shí)現(xiàn)類:

public class CustomGetCryptorServiceImpl implements CustomGetCryptorService {
    private static final Log log = LogFactory.getLog(CustomGetCryptorServiceImpl.class);
    @Override
    public String getRemoteCryptor(String url, String key) {
        // todo 自定義遠(yuǎn)程獲取密鑰
        log.info("starter獲取遠(yuǎn)程密鑰失敗");
        return null;
    }
}

3.3 工具類

public class CommonTool {
    public static String getMessage(String message,String prefix,String suffix){
        int prefixIndex = message.indexOf(prefix);
        int suffixIndex = message.lastIndexOf(suffix);
        return message.substring(prefixIndex+prefix.length(),suffixIndex);
    }
}
public class IdaasKaiserUtil {
        /**
         * 使用凱撒加密方式加密數(shù)據(jù)
         * @param orignal :原文
         * @param key     :密鑰
         * @return :加密后的數(shù)據(jù)
         */
        public static String encryptKaiser(String orignal, int key) {
            // 將字符串轉(zhuǎn)為字符數(shù)組
            char[] chars = orignal.toCharArray();
            StringBuilder sb = new StringBuilder();
            // 遍歷數(shù)組
            for (char aChar : chars) {
                // 獲取字符的ASCII編碼
                int asciiCode = aChar;
                // 偏移數(shù)據(jù)
                asciiCode += key;
                // 將偏移后的數(shù)據(jù)轉(zhuǎn)為字符
                char result = (char) asciiCode;
                // 拼接數(shù)據(jù)
                sb.append(result);
            }
            return sb.toString();
        }
        /**
         * 使用凱撒加密方式解密數(shù)據(jù)
         * @param encryptedData :密文
         * @param key           :密鑰
         * @return : 源數(shù)據(jù)
         */
        public static String decryptKaiser(String encryptedData, int key) {
            // 將字符串轉(zhuǎn)為字符數(shù)組
            char[] chars = encryptedData.toCharArray();
            StringBuilder sb = new StringBuilder();
            // 遍歷數(shù)組
            for (char aChar : chars) {
                // 獲取字符的ASCII編碼
                int asciiCode = aChar;
                // 偏移數(shù)據(jù)
                asciiCode -= key;
                // 將偏移后的數(shù)據(jù)轉(zhuǎn)為字符
                char result = (char) asciiCode;
                // 拼接數(shù)據(jù)
                sb.append(result);
            }
            return sb.toString();
        }
}

以上是自定義starter的自動(dòng)配置類的寫(xiě)法,這里列出了主要內(nèi)容,忽略了引包,和場(chǎng)景啟動(dòng)器的寫(xiě)法,如需細(xì)化請(qǐng)參看前一博客關(guān)于自定義starter的寫(xiě)法。

4、調(diào)用方的配置(調(diào)用方即誰(shuí)引用我的這個(gè)starter)

4.1、引入starter

<dependency>
    <groupId>com.pingan.idaas</groupId>
    <artifactId>data-decrypt-boot-starter</artifactId>
</dependency>

注意:這里的要返顯的字段不要寫(xiě)在要傳入的字段中,即這里的message1……7不要寫(xiě)在 atguigu.hello下面.

4.2、配置yml

idaas:
  decerypt:
      decryptPassword: 12345678 # 最低配置,必須
      url: wwww.baidu.com  #starter去遠(yuǎn)程獲取密鑰的地址(根據(jù)實(shí)際配置,若沒(méi)有去遠(yuǎn)程獲取可不配),非必須
      customGetCryptorClass: com.athaite.idaas.CustomGetCryptor  #客戶端自己代碼去遠(yuǎn)程獲取密鑰的類(此類要實(shí)現(xiàn)我們starter的接口CustomGetCryptorService),非必須

剩下的就是自己加密的部分了:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: IDSREN(IEN(憸憲憰憱憈憻懇懁憿憺憈慽慽慿憇憀慼慿憄憆慼慿憆憁慼慿憀憇憈憁憁慾憄慽憵懃憺憷憻憯憺憺憭憯憲憻憷憼?wèi)x懃懁憳憡憡憚憋憴憯憺懁憳慴憯憺憺憽懅憛懃憺懂憷憟懃憳懀憷憳懁憋懂懀懃憳慴懃懁憳憣?xiě)犮缿枒棏槺锒畱槕b憱憶憯懀憯憱懂憳懀憓憼?wèi)枒椼缿爲(wèi)毐飸寫(xiě)嬨緫g憆慴憯懃懂憽憠憳憱憽憼?wèi)爲(wèi)槕柖锒畱?)
      #url: jdbc:mysql://192.168.183.129:3306/gulimall_admin?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
      #username: root
      username: AIDSREN(AEN(懀憽憽懂))
      #password: 420188
      password: AIDSREN(AEN(憂憀慾慿憆憆))

特別提醒

本starter兼容本地解密,starter遠(yuǎn)程解密,客戶端自己遠(yuǎn)程解密

示例(4種類型):

  • 本地解密 :AIDSREN(AEN(懀憽憽懂)) 
  • 本地不解密 :AIDSREN(root)
  • 遠(yuǎn)程解密(雙冒號(hào)后是遠(yuǎn)程獲取失敗采用本地密文密鑰):AIDSREN(name::AEN(懀憽憽懂))
  • 遠(yuǎn)程解密(雙冒號(hào)后是遠(yuǎn)程獲取失敗采用本地明文密鑰):AIDSREN(name::root)

其他配置項(xiàng)與雙冒號(hào)(::)錯(cuò)開(kāi),避免誤判

自此,starter的自定義獲取配置文件傳參、執(zhí)行業(yè)務(wù)方法、獲取返回?cái)?shù)據(jù)就寫(xiě)完了。優(yōu)點(diǎn)是對(duì)代碼無(wú)侵入,可插拔,可自定義前后綴加解密方法,留下了遠(yuǎn)程獲取的口子,缺點(diǎn)是只有啟動(dòng)時(shí)加載一次,不能動(dòng)態(tài)感知變化。

四、jasypt原理分析

①M(fèi)ETA-INF/spring.factories 指定的入口類JasyptSpringCloudBootstrapConfiguration

②在這個(gè)類中通過(guò)@Import引入 EnableEncryptablePropertiesConfiguration

③在EnableEncryptablePropertiesConfiguration中加載了一個(gè)叫EnableEncryptablePropertiesBeanFactoryPostProcessor

④EnableEncryptablePropertiesBeanFactoryPostProcessor實(shí)現(xiàn)了一個(gè)接口BeanFactoryPostProcessor,Ordered重寫(xiě)了一個(gè)方法 叫postProcessBeanFactory

  • BeanFactoryPostProcessor:Bean工廠后處理器,在BeanDefinitionMap填充完畢,Bean實(shí)例化之前執(zhí)行
  • BeanPostProcessor:Bean后處理器,一般在Bean實(shí)例化之后,填充到單例池singletonObjects之前執(zhí)行。初始化前后分別執(zhí)行postProcessBeforeInitializationpostProcessAfterInitialization

該方法中的主要邏輯就是,獲取所有的propertySources。

獲取所有配置文件:MutablePropertySources propSources = environment.getPropertySources();

⑤判斷配置文件中的屬性是否是加密過(guò)(是否有指定前綴后綴)

⑥解密

五、springboot加載外部starter的原理(自動(dòng)配置原理)

springboot加載外部starter的原理:

①springboot的啟動(dòng)類有一個(gè)注解叫@SpringBootApplication

②該注解是個(gè)復(fù)合注解,其中有一個(gè)@EnableAutoConfiguration

③@EnableAutoConfiguration 也是復(fù)合注解 其中就有 @Import(AutoConfigurationImportSelector.class)

④AutoConfigurationImportSelector類中有getCandidateConfigurations方法

⑤getCandidateConfigurations 方法的loadSpringFactories會(huì)去讀配置文件META-INF/spring.factories文件

⑥該文件的org.springframework.boot.autoconfigure.EnableAutoConfiguration指定的類會(huì)被加載到

spring容器,這就完成了springboot加載外部bean或者第三方j(luò)ar中的bean

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • spring?security?自定義Provider?如何實(shí)現(xiàn)多種認(rèn)證

    spring?security?自定義Provider?如何實(shí)現(xiàn)多種認(rèn)證

    這篇文章主要介紹了spring?security?自定義Provider實(shí)現(xiàn)多種認(rèn)證方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Hadoop之Mapreduce序列化

    Hadoop之Mapreduce序列化

    本文主要帶我們了解Mapreduce序列化,序列化就是把內(nèi)存中的對(duì)象,轉(zhuǎn)換成字節(jié)序列(或其他數(shù)據(jù)傳輸協(xié)議)以便于存儲(chǔ)到磁盤(pán)(持久化)和網(wǎng)絡(luò)傳輸。想進(jìn)一步了解更多的小伙伴,可以參考閱讀本文
    2023-03-03
  • log4j2 RollingRandomAccessFile配置過(guò)程

    log4j2 RollingRandomAccessFile配置過(guò)程

    這篇文章主要介紹了log4j2 RollingRandomAccessFile配置過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 解決java報(bào)錯(cuò):使用mybatis?plus查詢一個(gè)只返回一條數(shù)據(jù)的sql,卻報(bào)錯(cuò)返回了1000多條問(wèn)題

    解決java報(bào)錯(cuò):使用mybatis?plus查詢一個(gè)只返回一條數(shù)據(jù)的sql,卻報(bào)錯(cuò)返回了1000多條問(wèn)題

    文章解釋了一個(gè)系統(tǒng)問(wèn)題,盡管SQL寫(xiě)了limit?1且MyBatis的debug日志顯示total為1,但仍返回了1805條數(shù)據(jù),原因是selectOne方法只查詢一條記錄,若有多條則報(bào)錯(cuò),而非智能篩選,文章還分析了MyBatisPlus和MyBatis中selectOne方法的不同實(shí)現(xiàn)
    2026-04-04
  • Swagger2匹配多個(gè)controller代碼實(shí)例

    Swagger2匹配多個(gè)controller代碼實(shí)例

    這篇文章主要介紹了Swagger2匹配多個(gè)controller代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • sqlmap 使用教程(從入門(mén)到進(jìn)階)

    sqlmap 使用教程(從入門(mén)到進(jìn)階)

    sqlmap是一款強(qiáng)大的開(kāi)源 SQL 注入自動(dòng)化測(cè)試工具,支持識(shí)別并利用多種類型的 SQL 注入漏洞(Boolean-based、Time-based、Error-based、Stacked Queries 等),本文給大家介紹sqlmap使用教程,感興趣的朋友一起看看吧
    2016-11-11
  • Spring配置擴(kuò)展之JavaConfig的使用小結(jié)

    Spring配置擴(kuò)展之JavaConfig的使用小結(jié)

    JavaConfig 是 Spring 框架中基于純 Java 代碼的配置方式,用于替代傳統(tǒng)的 XML 配置,通過(guò)注解(如@Bean)定義 Spring 容器的組件和依賴關(guān)系,使配置更加類型安全且易于維護(hù),感興趣的可以了解一下
    2025-12-12
  • Shiro集成Spring之注解示例詳解

    Shiro集成Spring之注解示例詳解

    Shiro想必大家都知道了,是目前使用率要比spring security都要多的一個(gè)權(quán)限框架,下面這篇文章主要給大家介紹了關(guān)于Shiro集成Spring之注解的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-09-09
  • Java Socket實(shí)現(xiàn)文件傳輸示例代碼

    Java Socket實(shí)現(xiàn)文件傳輸示例代碼

    這篇文章主要介紹了Java Socket實(shí)現(xiàn)文件傳輸示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • SpringBoot中的Profile多環(huán)境配置方法

    SpringBoot中的Profile多環(huán)境配置方法

    這篇文章主要介紹了SpringBoot中的Profile多環(huán)境配置,SpringBoot提供了兩種多環(huán)境配置的方式,分別是使用profile文件進(jìn)行多環(huán)境配置以及使用@Profile注解進(jìn)行多環(huán)境配置,需要的朋友可以參考下
    2023-01-01

最新評(píng)論

和政县| 灵丘县| 淮南市| 汤阴县| 喜德县| 抚远县| 大英县| 秭归县| 乌拉特中旗| 华容县| 盘山县| 永修县| 黄梅县| 三亚市| 保亭| 长春市| 公主岭市| 龙门县| 康平县| 三门峡市| 三亚市| 岚皋县| 府谷县| 眉山市| 浪卡子县| 崇仁县| 来安县| 邢台县| 桑日县| 旬邑县| 宜州市| 通化县| 博罗县| 新巴尔虎右旗| 永昌县| 云阳县| 偏关县| 双桥区| 建昌县| 于都县| 涪陵区|