spring和springboot中加密連接數(shù)據(jù)庫的信息

前言:

在實(shí)際開發(fā)中,一些關(guān)鍵的信息肯定是要加密的,否則就太不安全了。比如連接數(shù)據(jù)庫的用戶名和密碼,一般就需要加密。接下來就看看spring項(xiàng)目和spring boot項(xiàng)目中分別是如何加密這些信息的。


歡迎大家關(guān)注我的公眾號(hào) javawebkf,目前正在慢慢地將簡書文章搬到公眾號(hào),以后簡書和公眾號(hào)文章將同步更新,且簡書上的付費(fèi)文章在公眾號(hào)上將免費(fèi)。


一、spring中加密連接數(shù)據(jù)庫的信息:

spring項(xiàng)目中,我們一般把連接數(shù)據(jù)庫的信息寫在jdbc.properties中,然后在spring-dao.xml中讀取配置信息。
未加密是這樣寫的:
jdbc.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123

然后在spring-dao.xml中讀?。?/p>

<context:property-placeholder location="classpath:jdbc.properties" />

要加密需要進(jìn)行以下操作:
1、編寫DES算法加密工具類:
DESUtil.java:

import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


/**
 * 用DES對稱算法加密數(shù)據(jù)庫連接的信息</br>
 * 所謂對稱算法就是加密和解密使用相同的key
 * 
 * @author zhu
 *
 */
public class DESUtil {
    private static Key key;
    // 設(shè)置密鑰key
    private static String KEY_STR = "myKey";
    private static String CHARSETNAME = "UTF-8";
    private static String ALGORITHM = "DES";

    static {
        try {
            // 生成des算法對象
            KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);
            // 運(yùn)用SHA1安全策略
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            // 設(shè)置密鑰種子
            secureRandom.setSeed(KEY_STR.getBytes());
            // 初始化基于SHA1的算法對象
            generator.init(secureRandom);
            // 生成密鑰對象
            key = generator.generateKey();
            generator = null;
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    /**
     * 獲取加密后的信息
     * 
     * @param str
     * @return
     */
    public static String getEncryptString(String str) {
        // 基于BASE64編碼,接收byte[]并轉(zhuǎn)換層String
        BASE64Encoder base64encoder = new BASE64Encoder();
        try {
            // utf-8編碼
            byte[] bytes = str.getBytes(CHARSETNAME);
            // 獲取加密對象
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            // 初始化密碼信息
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // 加密
            byte[] doFinal = cipher.doFinal(bytes);
            // 返回
            return base64encoder.encode(doFinal);
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    /**
     * 獲取解密之后的信息
     * 
     * @param str
     * @return
     */
    public static String getDecryptString(String str) {
        //基于BASE64編碼,接收byte[]并轉(zhuǎn)換成String
        BASE64Decoder base64decoder = new BASE64Decoder();
        try {
            //將字符串decode成byte[]
            byte[] bytes = base64decoder.decodeBuffer(str);
            //獲取解密對象
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            //初始化解密信息
            cipher.init(Cipher.DECRYPT_MODE, key);
            //解密
            byte[] doFinal = cipher.doFinal(bytes);
            //返回解密之后的信息
            return new String(doFinal,CHARSETNAME);
        }catch(Exception e) {
            throw new RuntimeException(e);
        }
    }
    
       /**
     * 測試
     * 
     * @param args
     */
    public static void main(String[] args) {
        // 加密root字符串
        System.out.println(getEncryptString("root"));
        // 加密123
        System.out.println(getEncryptString("123"));
        // 解密WnplV/ietfQ=
        System.out.println(getDecryptString("WnplV/ietfQ="));
    }
}

這個(gè)類就實(shí)現(xiàn)了DES算法加密字符串,把需要加密的字段傳入getEncryptString方法即可加密??催\(yùn)行效果:

image.png

注意:
在編寫這個(gè)類的時(shí)候,BASE64Encoder一直報(bào)錯(cuò),找不到 sun.misc.BASE64Encoder包,沒辦法import這個(gè)包。
解決辦法:
選中項(xiàng)目 ---> build path ---> libraries ---> jre system library ---> access rules
---> edit ---> add ---> accessble ---> ** ---> ok
image.png

image.png

2、把jdbc.properties中的字段換成加密后的
jdbc.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test?useUnicode=true&characterEncoding=utf8
jdbc.username=WnplV/ietfQ=
jdbc.password=um461kxL7IU=

3、在spring讀取配置時(shí)解密
以上兩步完成了加密,但是這樣spring讀取時(shí)并不會(huì)自動(dòng)解密這些經(jīng)過加密的字段,所以還需要進(jìn)行如下操作:
EncryptPropertyPlaceholderConfigurer.java:

import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

/**
 * 在spring-dao加載jdbc.properties時(shí),將加密信息解密出來
 * 
 * @author zhu
 *
 */
public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    // 需要加密的字段數(shù)組
    private String[] encryptPropNames = { "jdbc.username", "jdbc.password" };

    protected String convertProperty(String propertyName, String propertyValue) {
        if (isEncryptProp(propertyName)) {
            // 對加密的字段進(jìn)行解密工作(調(diào)用DESUtil中的解密方法)
            String decryptValue = DESUtil.getDecryptString(propertyValue);
            return decryptValue;
        } else {
            return propertyValue;
        }
    }

    /**
     * 該屬性是否已加密
     * 
     * @param propertyName
     * @return
     */
    private boolean isEncryptProp(String propertyName) {
        // 若等于需要加密的field,則進(jìn)行加密
        for (String encryptpropertyName : encryptPropNames) {
            if (encryptpropertyName.equals(propertyName)) {
                return true;
            }
        }
        return false;
    }

}

這段代碼就對jdbc.username和jdbc.password進(jìn)行了解密。然后在spring-dao.xml中以如下方式讀取jdbc.properties:
spring-dao.xml:

    <bean
        class="com.zhu.util.EncryptPropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:jdbc.properties</value>
            </list>
        </property>
        <property name="fileEncoding" value="UTF-8" />
    </bean>

這里就把EncryptPropertyPlaceholderConfigurer配置成了bean,用這個(gè)類去讀取jdbc.properties就可以解密了。

4、連接測試:
DESTest.java:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mysql.jdbc.Driver;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:spring/spring-dao.xml"})
public class DESTest {
    
    @Test
    public void testGetDataSource() {
        System.out.println(Driver.class);
    }

}

運(yùn)行結(jié)果:


image.png

連接成功!

二、springboot項(xiàng)目中加密數(shù)據(jù)庫連接信息:

springboot項(xiàng)目沒有jdbc.properties,也沒有spring-dao.xml,全都寫在application.properties或application.yml中。需要加密的話執(zhí)行如下操作即可:

1、引入jasypt的jar包:

        <dependency>
            <groupId>com.github.ulisesbocchio</groupId>
            <artifactId>jasypt-spring-boot-starter</artifactId>
            <version>1.16</version>
        </dependency>

2、在application.properties中配置加密key:
這個(gè)key可以自己隨便寫,我寫的是hellospringboot。

#配置數(shù)據(jù)源加密的密鑰
jasypt.encryptor.password=hellospringboot

3、使用jasypt加密字段:

import org.jasypt.encryption.StringEncryptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class test {
    
    //注入StringEncryptor
    @Autowired
    StringEncryptor encryptor;
    
    @Test
    public void encry() {
        //加密root
        String username = encryptor.encrypt("root");
        System.out.println(username);
        //加密123
        String password = encryptor.encrypt("123");
        System.out.println(password);
    }
}

運(yùn)行結(jié)果:

image.png

這兩個(gè)就是root和123加密后的結(jié)果。
注意:
這個(gè)測試類每運(yùn)行一次輸出的結(jié)果都是不一樣的,比如第一次運(yùn)行是上圖結(jié)果,第二次運(yùn)行加密結(jié)果又不一樣了,這是正常現(xiàn)象。隨便復(fù)制哪一次的運(yùn)行結(jié)果到application.properties中都行。

4、在application.properties中配置連接數(shù)據(jù)庫的信息:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql:///meilianMall?useUnicode=true&characterEncoding=utf8
spring.datasource.username=ENC(UltArcVy251RWehUvajQmg==)
spring.datasource.password=ENC(y23g0pb97XsBULm3ILNWTg==)

注意:
加密字段需要用ENC(密文)的形式,直接寫spring.datasource.username=UltArcVy251RWehUvajQmg是無效的。

5、連接測試:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.mysql.jdbc.Driver;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class test {

    @Test
    public void testGetDataSource() {
        System.out.println(Driver.class);
    }
    
}
image.png

可以看到也是連接成功的。

總結(jié):

spring項(xiàng)目中加密數(shù)據(jù)庫連接信息的方法稍微麻煩一點(diǎn),要加密又要解密,而springboot采用的jasypt加密相當(dāng)于解密工作它會(huì)自動(dòng)完成,我們只需要在application.properties中配置密鑰和加密后的信息即可。

以上內(nèi)容屬于個(gè)人筆記整理,如有錯(cuò)誤,歡迎批評指正!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容