spring boot配置文件自定义加密配置

公司漏洞检测,检测到 线上的jar包中配置文件里面数据库密码 ,redis密码等等配置都是明文,所以需要在配置文件中加密。所以为了实现该功能直接贴代码
贴一下原作者的git(原文章忘记在哪里了),感谢大佬

https://gitee.com/pychfarm_admin/encryption/tree/main

这里定义加密,解密方法,同时配置公钥,私钥
public class MyEncryptUtil {

    public static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBOkkkvjbOQ6UTCo8U4bRC/EcEtxz8haHg6lueM3NBbH3eIT7kfwQFOqj1h1qPGcQNeyn4vxzMWBAKzSQehjqVBL7/8GN7EZ7TEaUuWO+8qsuZnOdrztX7bNKACnks+SelmtbrbnFKUMAq2c2mS0o1V6iwyRxJYLGaHGXnz4KSkwIDAQAB";

    public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIE6SSS+Ns5DpRMKjxThtEL8RwS3HPyFoeDqW54zc0Fsfd4hPuR/BAU6qPWHWo8ZxA17Kfi/HMxYEArNJB6GOpUEvv/wY3sRntMRpS5Y77yqy5mc52vO1fts0oAKeSz5J6Wa1utucUpQwCrZzaZLSjVXqLDJHElgsZocZefPgpKTAgMBAAECgYAFaCDjTqoQWzgu4cQ2xXK7Ur7N7bNixVyOgn+u0MxDsnxZrN5qxP2wElI7Y5xgXF2diseoxqY3zn9tVEPsmwUcY73naoosx9V8oExgT/BUkZYIzj1ei08zOr984zl3dbFcxOCRvqywXj9FAAGx1mhmCzFCIauJg3aX0S9mt5/CwQJBAMYZsmMQ9owoXZuSclKVRfMHFpAPhQlcBM4xadhX0IRYATgNTxpESmcCoGWvyw3bvieNJyC9Njx6X4FJ2EZUzhECQQCm/2IM5MlsCwyKtME5RPFna2hSqYU80UzkNfDIyMokcU2JUI4Fhigog4ol0GFMiMBsHIjS+cJiAwNbIsq5rsJjAkA94yVBobkETFACHBwvBIdXxy0bUF3lcKPnrrQ8bCKuVbf7xNyjfhYoXD+zxNmQuMeNH6HLrpDVD/3qLCGuxyuhAkAiLPl/8gJWnhw+9qbkdXuB0rVS1WZy/9JgkblpHc5gjt9zTo0CDGaDhAftnSuMYiAe/+fwZTSmoj85k3ExdtZJAkEArJuG/NWY9HP4p7jtZX9rMokyB3517v7HQdJKBDIlOzseRC/roCvU8LQ/URDFBUqXCRgedxgW+0ZmKFf4xeawqw==";

    public static void main(String[] args) throws Exception {
        String message = "jfyt_1234";
        System.out.println("原始字符串: " + message);
        String messageEn = encrypt(message, PUBLIC_KEY);
        System.out.println("加密后的字符串为: " + messageEn);
        String messageDe = decrypt(messageEn, PRIVATE_KEY);
        System.out.println("还原后的字符串为: " + messageDe);
    }


    public static void generateKey() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(1024, new SecureRandom());
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  // 得到私钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
        System.out.println("当前生成的公钥= " + publicKeyString);
        System.out.println("当前生成的私钥= " + privateKeyString);
    }

    public static String encrypt(String str, String publicKey) throws NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException {
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
    }

    public static String decrypt(String str, String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
        byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return new String(cipher.doFinal(inputByte));
    }

}
这里定义异常信息
public class PrivateKeyFindError extends Exception{
    public PrivateKeyFindError() {
        super();
    }

    public PrivateKeyFindError(String message) {
        super(message);
    }

    public PrivateKeyFindError(String message, Throwable cause) {
        super(message, cause);
    }

    public PrivateKeyFindError(Throwable cause) {
        super(cause);
    }

    protected PrivateKeyFindError(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}
这里 我们获取配置文件中的加密配置,然后解密,主要通过前缀后缀的修改
public class EnableEncryptionData implements BeanFactoryPostProcessor, Ordered {

    public static final String PREFIX_PROPERTY = "encryption.prefix";

    public static final String SUFFIX_PROPERTY = "encryption.suffix";

    public static final String RSA_PUBLIC_KEY_PROPERTY = "encryption.rsa.publicKey";

    public static final String RSA_PRIVATE_KEY_PROPERTY = "encryption.rsa.privateKey";

    public static final String DEFAULT_PREFIX = "PWD[";

    public static final String DEFAULT_SUFFIX = "]";

    public static final String HF_PRIVATE_KEY_PATH = "hf_private_key";

    private static final Logger LOG = LoggerFactory.getLogger(EnableEncryptionData.class);

    private static final Properties properties = new Properties();

    private final ConfigurableEnvironment environment;

    private String prefix;

    private String suffix;

    private String privateKey;

    public EnableEncryptionData(ConfigurableEnvironment environment) {
        this.environment = environment;
    }

    @SneakyThrows
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        MutablePropertySources propertySources = environment.getPropertySources();
        for (PropertySource<?> propertySource : propertySources) {
            if (propertySource.getSource() instanceof Map) {
                Map<String, Object> source = (Map) propertySource.getSource();

                for (String key : source.keySet()){
                    String property = environment.getProperty(key);
                    if(hasPreAndSuf(property)) {
                        Map<String, Object> properties = new HashMap<>();
                        String relay = splitPreAndSuf(property, this.prefix, this.suffix);
                        String decrypt = MyEncryptUtil.decrypt(relay, getPrivateKey(environment));
                        properties.put(key, decrypt);
                        propertySources.addFirst(new MapPropertySource(getRandStr(5),properties));
                    }
                }

这里是原博客作者代码块,但是我在实际使用时发现  source.put(k, decrypt) 将解密后的配置进行写入时候,
出现了map java.lang.UnsupportedOperationException异常,主要原因是
,从配置文件中读取到的参数是只读的,不可修改,所以source.put()会抛异常,
所以改成了propertySources.addFirst(new MapPropertySource(getRandStr(5),properties));
//                source.forEach((k, v) -> {
//                    String property = environment.getProperty(k);
//                    if (hasPreAndSuf(property)) {
//                        LOG.info("开始处理 k = [{}]", k);
//                        try {
//                            String relay = splitPreAndSuf(property, this.prefix, this.suffix);
//                            String decrypt = MyEncryptUtil.decrypt(relay, getPrivateKey(environment));
//                            source.put(k, decrypt);
//                        }
//                        catch (Exception e) {
//                            LOG.error("e = ", e);
//                        }
//                    }
//                });
            }
        }
    }
    public static String getRandStr(int num){
        String strs = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuffer buff = new StringBuffer();
        for(int i=1;i<=num;i++){
            char str = strs.charAt((int)(Math.random() * 26));
            buff.append(str);
        }
        return buff.toString();
    }
    private String getPrivateKey(ConfigurableEnvironment environment) throws PrivateKeyFindError {

        return MyEncryptUtil.PRIVATE_KEY;

//        throw new PrivateKeyFindError("rsa private key is null!");
    }
判断配置文件中的参数是否以我们定义的前缀后缀结尾
    private boolean hasPreAndSuf(String property) {
        return property.startsWith(getPrefix(environment)) && property.endsWith(getSuffix(environment));
    }

    protected String splitPreAndSuf(String str, String prefix, String suffix) {
        return str.replace(prefix, "").replace(suffix, "");
    }

    private String getSuffix(ConfigurableEnvironment environment) {
        this.suffix = environment.getProperty(SUFFIX_PROPERTY);
        if (StringUtils.hasLength(suffix)) {
            return this.suffix;
        }
        this.suffix = DEFAULT_SUFFIX;
        return DEFAULT_SUFFIX;
    }

    private String getPrefix(ConfigurableEnvironment environment) {
        this.prefix = environment.getProperty(PREFIX_PROPERTY);
        if (StringUtils.hasLength(prefix)) {
            return this.prefix;
        }
        this.prefix = DEFAULT_PREFIX;
        return DEFAULT_PREFIX;
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 100;
    }

    static {
        InputStream resource = Thread.currentThread().getContextClassLoader().getResourceAsStream(HF_PRIVATE_KEY_PATH);
        try {
            if (resource != null) {
                properties.load(resource);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

进行启动配置
@Configuration
public class CustomerBean {
    @Bean
    public static EnableEncryptionData enableEncryptionData(final ConfigurableEnvironment environment) {

        return new EnableEncryptionData(environment);
    }
}

到这里已经完成了,接下来看一下配置文件如何使用

以PWD[为前缀,]为后缀
app.db.password=PWD[baII5Yc8yLoBudUwYI5OlclhZ41Qz34Z1b/MjEuKuhbFVlXKQ65fZQgdwMiSR+CXp/1j3aLHpAN16857H7fZxWz+iT/ldiBVNk4kn+VKQ2mBZVXnvRclXKqJ7/9YSecg1JCkmLRaHFyVjudmMXJikjtvKVIimKstYY5sdHFUqTY=]

有一点小问题,需要先将密码加密然后再进行配置,

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值