日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
聊聊Sharding-JDBC數(shù)據(jù)脫敏

安全控制一直是治理的重要環(huán)節(jié),數(shù)據(jù)脫敏屬于安全控制的范疇。對互聯(lián)網(wǎng)公司、傳統(tǒng)行業(yè)來說,數(shù)據(jù)安全一直是極為重視和敏感的話題。

創(chuàng)新互聯(lián)是一家專業(yè)提供黔西南州企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站建設(shè)、成都做網(wǎng)站、html5、小程序制作等業(yè)務(wù)。10年已為黔西南州眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進(jìn)行中。

數(shù)據(jù)脫敏是指對某些敏感信息通過脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù)。

涉及客戶安全數(shù)據(jù)或者一些商業(yè)性敏感數(shù)據(jù),如身份證號、手機(jī)號、卡號、客戶號等個人信息按照相關(guān)部門規(guī)定,都需要進(jìn)行數(shù)據(jù)脫敏。

今天來深入聊一下 Sharding-JDBC 如何對敏感數(shù)據(jù)脫敏,僅在持久層脫敏。

幾個重要概念

Sharding-JDBC 在底層進(jìn)行了脫敏的封裝,讓開發(fā)人員在無感知的情況下進(jìn)行數(shù)據(jù)脫敏,來看一下官方的詳情圖,如下:

下面針對上圖中涉及到的幾個名詞進(jìn)行詳細(xì)的解釋,在下文實(shí)戰(zhàn)中做個鋪墊。

1. 數(shù)據(jù)源配置

這個就是Datasource的配置。

2. 加密器配置

加密器就涉及到數(shù)據(jù)脫敏了,Sharding-JDBC 內(nèi)置了兩個加密器,如下:

  • MD5Encryptor:MD5加密算法,一種不可逆的加密方式,通常用來對密碼進(jìn)行加密
  • AESEncryptor:AES加密算法,一種可逆的加密方式,通常用來對回顯的字段加密,比如身份證、手機(jī)號碼

Sharding-JDBC還支持自定義加密器。

3. 脫敏表配置

用于告訴 Sharding-JDBC 數(shù)據(jù)表里哪個列用于存儲密文數(shù)據(jù)(cipherColumn)、哪個列用于存儲明文數(shù)據(jù)(plainColumn)以及用戶想使用哪個列進(jìn)行SQL編寫(logicColumn):

  • logicColumn:邏輯列,這個和前文中邏輯表類似,用于實(shí)際的SQL編寫,比如數(shù)據(jù)庫中真實(shí)字段是cipher_pwd,但是在Sharding-JDBC配置時指定邏輯列的名稱為:pwd,那么在寫SQL的時候就要使用邏輯列pwd進(jìn)行查詢。
  • cipherColumn:存儲密文數(shù)據(jù)的字段
  • plainColumn:存儲明文數(shù)據(jù)的字段,一般不使用,不然脫敏也毫無意義

4. 查詢屬性的配置

當(dāng)?shù)讓訑?shù)據(jù)庫表里同時存儲了明文數(shù)據(jù)、密文數(shù)據(jù)后,該屬性開關(guān)用于決定是直接查詢數(shù)據(jù)庫表里的明文數(shù)據(jù)進(jìn)行返回,還是查詢密文數(shù)據(jù)通過Encrypt-JDBC解密后返回。

數(shù)據(jù)脫敏實(shí)戰(zhàn)

基本概念介紹完了,下面就使用Sharding-JDBC進(jìn)行數(shù)據(jù)脫敏。

這里就不再演示分庫分表了,直接用單庫進(jìn)行脫敏演示。

1. 新建表

筆者這里新建了一張用戶表t_user,如下:

CREATE TABLE `t_user` (
`user_id` bigint(20) NOT NULL COMMENT '用戶唯一ID',
`fullname` varchar(50) DEFAULT NULL COMMENT '名字',
`user_type` varchar(255) DEFAULT NULL COMMENT '類型',
`cipher_pwd` varchar(255) DEFAULT NULL COMMENT '密碼',
`mobile` varchar(100) DEFAULT NULL COMMENT '手機(jī)號',
`mobile_data` varchar(100) DEFAULT NULL COMMENT '手機(jī)號',
`id_card` varchar(60) DEFAULT NULL COMMENT '身份證',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 數(shù)據(jù)源配置

數(shù)據(jù)源這里使用單數(shù)據(jù)源,配置很簡單,上篇文章也演示過,配置如下:

spring:
# Sharding-JDBC的配置
shardingsphere:
datasource:
names: ds
# 數(shù)據(jù)源ds配置
ds:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/user_db?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456

3. 加密器聲明

需要用到什么加密器需要事先在配置文件中聲明,這樣才能在字段中去引用,配置如下:

spring:
encrypt:
encryptors:
# md5加密算法-sharding-jdbc內(nèi)置的算法,這里名稱任意
encryptor_md5:
# 別名,這里一定要是MD5
type: MD5
# aes加密算法-sharding-jdbc內(nèi)置的算法,這里名稱任意
encryptor_aes:
# 別名,這里一定要是aes
type: aes
props:
# 設(shè)置秘鑰
aes.key.value: myjszl

上述總計(jì)配置了兩種Sharding-JDBC內(nèi)置的加密器,如下:

  • encryptor_md5:MD5Encryptor加密器,這里的名稱可以任意,但是type這個屬性一定要是MD5
  • encryptor_aes:AESEncryptor加密器,對稱加密算法,因此需要指定加密的秘鑰:aes.key.value

Sharding-JDBC指定規(guī)則如下:

#加解密器類型,可自定義或選擇內(nèi)置類型:MD5/AES 
spring.shardingsphere.encrypt.encryptors..type=

#屬性配置, 注意:使用AES加密器,需要配置AES加密器的KEY屬性:aes.key.value
spring.shardingsphere.encrypt.encryptors..props.=

4. 對數(shù)據(jù)脫敏配置

下面針對三個字段進(jìn)行脫敏,如下:

  • cipher_pwd:密碼使用不可逆的加密器MD5Encryptor
  • id_card:身份證使用可逆的加密器AESEncryptor
  • mobile:手機(jī)號使用可逆的加密器AESEncryptor

詳細(xì)的配置如下:

spring:
# Sharding-JDBC的配置
shardingsphere:
encrypt:
tables:
t_user:
columns:
# 邏輯列,sharding-jdbc中寫SQL需要用到的列
password:
# 存儲明文的字段
#plainColumn: password
# 存儲密文的字段
cipherColumn: cipher_pwd
# 指定加密器
encryptor: encryptor_md5
# 身份證號的邏輯列,使用aes這種可逆的加密算法
id_card:
cipherColumn: id_card
encryptor: encryptor_aes
# 手機(jī)號的邏輯列,使用aes這種可逆的加密算法
mobile:
cipherColumn: mobile
encryptor: encryptor_aes

Sharding-JDBC 指定的規(guī)則如下:

spring.shardingsphere.encrypt.tables..columns..encryptor= #加密器名字

spring.shardingsphere.encrypt.tables..columns..plainColumn= #存儲明文的字段

spring.shardingsphere.encrypt.tables..columns..cipherColumn= #存儲密文的字段

注意:上述配置中的密碼這個字段,數(shù)據(jù)庫表中的真實(shí)字段是cipher_pwd,但是這里筆者指定的邏輯列是password,因此在寫SQL的時候,一定要寫password這個邏輯列,比如查詢的SQL,如下:

SELECT
password AS cipherPwd,
fullname,
user_type,
id_card AS id_card
FROM
t_user where user_id=?

現(xiàn)在向其中插入幾條數(shù)據(jù)看看效果,單元測試如下:

@Test
public void testInsertUser() {
for (int i = 0; i < 10; i++) {
User user = new User();
user.setFullName("不才陳某");
user.setCipherPwd("abc123");
user.setIdCard("320829198708012232");
user.setUserId((long)i);
user.setMobile("13852331509");
userMapper.insertUser(user);
}
}

數(shù)據(jù)如下:

可以看到數(shù)據(jù)持久化到數(shù)據(jù)庫中已經(jīng)脫敏了。

問題來了:那么查詢的效果出來的效果是什么?

試想一下,MD5加密器是不可逆的,AES加密器是可逆的,那么符合正常邏輯的狀態(tài)下就應(yīng)該是密碼這個字段查詢出來的還是密文(不可逆),身份證、手機(jī)號查詢出來的應(yīng)該是明文。

新建查詢的單元測試,如下:

@Test
public void testList() throws JsonProcessingException {
List users = userMapper.listAll();
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(users);
System.out.println(json);
}

結(jié)果如下:

很清楚了,一切都朝著我們的預(yù)料的方向發(fā)展~

限制條件

字段進(jìn)行脫敏后在寫SQL時有一些操作是不支持的,如下:

  • 脫敏字段無法支持比較操作,如:大于小于、ORDER BY、BETWEEN、LIKE等。
  • 脫敏字段無法支持計(jì)算操作,如:AVG、SUM以及計(jì)算表達(dá)式 。

原理

其實(shí)Sharding-JDBC數(shù)據(jù)脫敏原理很簡單,看一下官方給的一張圖:

1. 插入數(shù)據(jù)

加密器有一個公共的接口Encryptor,如下:

public interface Encryptor extends TypeBasedSPI {

/**
* Initialize.
*/
void init();

/**
* Encode.
*
* @param plaintext plaintext
* @return ciphertext
*/
String encrypt(Object plaintext);

/**
* Decode.
*
* @param ciphertext ciphertext
* @return plaintext
*/
Object decrypt(String ciphertext);
}

當(dāng)插入數(shù)據(jù)涉及到加密字段,即是定義的邏輯列,那么Sharding-JDBC內(nèi)部會將這條SQL改寫,將邏輯列替換成表的真實(shí)列,并且調(diào)用 encrypt(Object plaintext)方法將明文加密成密文后存儲進(jìn)去。

2. 更新數(shù)據(jù)

更新和插入數(shù)據(jù)一樣,同樣會將SQL改寫,調(diào)用encrypt(Object plaintext)方法將明文加密成密文后存儲進(jìn)去。

3. 查詢數(shù)據(jù)

查詢數(shù)據(jù)就比較復(fù)雜了,這里只討論默認(rèn)情況,則是使用加密列查詢,默認(rèn)配置如下:

spring.shardingsphere.props.query.with.cipher.column=true

查詢分為兩類,如下:

(1) where條件中不帶脫敏邏輯列

這種情況也就是在查詢結(jié)果集中涉及到脫敏的邏輯列,但是在查詢條件中不涉及,那么在返回結(jié)果的時候則會調(diào)用加密器的解密方法Object decrypt(String ciphertext)去將結(jié)果解密返回。

(2) where條件中帶脫敏邏輯列

這種情況就比較復(fù)雜了,where條件中涉及了脫敏邏輯列,那么在改寫SQL時會調(diào)用加密器的加密方法String encrypt(Object plaintext)將其加密成密文去查詢;

同樣返回結(jié)果集也會調(diào)用加密器的解密方法Object decrypt(String ciphertext)去將結(jié)果解密返回。

加密策略

Sharding-JDBC默認(rèn)提供了兩種內(nèi)置的加密器,但是實(shí)際開發(fā)中這兩種肯定是不夠用的,需要開發(fā)人員去自定義加密器應(yīng)該各種場景。

Sharding-JDBC提供了兩類加密策略接口,如下:

1. Encryptor

提供encrypt(), decrypt()兩種方法對需要脫敏的數(shù)據(jù)進(jìn)行加解密;在用戶進(jìn)行INSERT, DELETE, UPDATE時,ShardingSphere會按照用戶配置,對SQL進(jìn)行解析、改寫、路由,并會調(diào)用encrypt()將數(shù)據(jù)加密后存儲到數(shù)據(jù)庫, 而在SELECT時,則調(diào)用decrypt()方法將從數(shù)據(jù)庫中取出的脫敏數(shù)據(jù)進(jìn)行逆向解密,最終將原始數(shù)據(jù)返回給用戶。

接口如下:

public interface Encryptor extends TypeBasedSPI {
void init();
String encrypt(Object plaintext);
Object decrypt(String ciphertext);
}

2. QueryAssistedEncryptor

相比較于第一種脫敏方案,該方案更為安全和復(fù)雜。它的理念是:即使是相同的數(shù)據(jù),如兩個用戶的密碼相同,它們在數(shù)據(jù)庫里存儲的脫敏數(shù)據(jù)也應(yīng)當(dāng)是不一樣的。這種理念更有利于保護(hù)用戶信息,防止撞庫成功。

它提供三種函數(shù)進(jìn)行實(shí)現(xiàn),分別是encrypt(), decrypt(), queryAssistedEncrypt()。在encrypt()階段,用戶通過設(shè)置某個變動種子,例如時間戳。針對原始數(shù)據(jù)+變動種子組合的內(nèi)容進(jìn)行加密,就能保證即使原始數(shù)據(jù)相同,也因?yàn)橛凶儎臃N子的存在,致使加密后的脫敏數(shù)據(jù)是不一樣的。在decrypt()可依據(jù)之前規(guī)定的加密算法,利用種子數(shù)據(jù)進(jìn)行解密。

雖然這種方式確實(shí)可以增加數(shù)據(jù)的保密性,但是另一個問題卻隨之出現(xiàn):相同的數(shù)據(jù)在數(shù)據(jù)庫里存儲的內(nèi)容是不一樣的,那么當(dāng)用戶按照這個加密列進(jìn)行等值查詢(SELECT FROM table WHERE encryptedColumnn = ?)時會發(fā)現(xiàn)無法將所有相同的原始數(shù)據(jù)查詢出來。

為此,我們提出了輔助查詢列的概念。該輔助查詢列通過queryAssistedEncrypt()生成,與decrypt()不同的是,該方法通過對原始數(shù)據(jù)進(jìn)行另一種方式的加密,但是針對原始數(shù)據(jù)相同的數(shù)據(jù),這種加密方式產(chǎn)生的加密數(shù)據(jù)是一致的。

將queryAssistedEncrypt()后的數(shù)據(jù)存儲到數(shù)據(jù)中用于輔助查詢真實(shí)數(shù)據(jù)。因此,數(shù)據(jù)庫表中多出這一個輔助查詢列。

由于queryAssistedEncrypt()和encrypt()產(chǎn)生不同加密數(shù)據(jù)進(jìn)行存儲,而decrypt()可逆,queryAssistedEncrypt()不可逆。在查詢原始數(shù)據(jù)的時候,會自動對SQL進(jìn)行解析、改寫、路由,利用輔助查詢列進(jìn)行 WHERE條件的查詢,卻利用 decrypt()對encrypt()加密后的數(shù)據(jù)進(jìn)行解密,并將原始數(shù)據(jù)返回給用戶。這一切都是對用戶透明化的。

簡單概括一下:

  • QueryAssistedEncryptor更加安全,加了一個變動因子一起加密,這樣即使內(nèi)容一樣加密后的密文也是不同的
  • 為了查詢方便,提供了一個輔助查詢列,這個輔助查詢列中的數(shù)據(jù)不帶變動因子,直接明文加密的,可以根據(jù)輔助查詢列查詢
  • 這一切的操作都是透明的,開發(fā)人員無須關(guān)心,只需要按照給定的規(guī)則配置

接口如下:

public interface QueryAssistedEncryptor extends Encryptor {
String queryAssistedEncrypt(String plaintext);
}

QueryAssistedEncryptor這類加密策略并無內(nèi)置的加密器,需要開發(fā)人員自定義實(shí)現(xiàn)。

如何自定義加密器

上文介紹到了Sharding-JDBC支持的兩種加密策略,肯定都是要實(shí)現(xiàn)一下,下面將會針對兩種策略去介紹一下如何自定義。

1. Encryptor 自定義實(shí)現(xiàn)

自定義很簡單,直接實(shí)現(xiàn)Encryptor 接口即可,重寫其中的加密、解密方法。

下面自定義一個SHA256加密算法器,這是一種不可逆的算法,如下:

/**
* @author 不才陳某 公眾號:碼猿技術(shù)專欄
* 自定義的加密解密算法,基于sha256
*/
@Data
public class Sha256HexEncryptor implements Encryptor {

/**
* 別名,配置時需要
*/
public final static String ALGORITHM_NAME="SHA256";

private Properties properties = new Properties();

@Override
public void init() {

}

/**
* 加密
* INSERT, DELETE, UPDATE時會調(diào)用該方法進(jìn)行加密存儲到數(shù)據(jù)庫中
* @param plaintext 明文
* @return 加密后的密文
*/
@Override
public String encrypt(final Object plaintext) {
if (null == plaintext) {
return null;
}
return DigestUtils.sha256Hex(String.valueOf(plaintext));
}

/**
* 解密
* 在SELECT 查詢會調(diào)用該方法進(jìn)行解密
* @param ciphertext 密文
* @return 由于sha256是一種不可逆的算法,因此直接返回密文
*/
@Override
public String decrypt(final String ciphertext) {
return ciphertext;
}

/**
* 別名,在配置中指定的名稱
*/
@Override
public String getType() {
return Sha256HexEncryptor.ALGORITHM_NAME;
}
}

加密解密的過程和MD5Encryptor加密器類似,不再詳細(xì)介紹了,很容易理解。

由于是使用SPI的方式,因此還需要在resource/META-INF/services目錄中新建一個org.apache.shardingsphere.encrypt.strategy.spi.Encryptor文件,內(nèi)容如下:

com.java.family.shardingjdbc003.encryptor.Sha256HexEncryptor

好了,現(xiàn)在這個SHA256加密器就已經(jīng)定義好了,可以在配置文件中配置了。

現(xiàn)在使用自定義SHA256加密器對密碼這個列進(jìn)行加密,分為如下步驟:

(1) 聲明加密器

聲明很簡單,配置如下:

spring:
# Sharding-JDBC的配置
shardingsphere:
encrypt:
encryptors:
# sha256加密算法,自定義的
encryptor_sha256:
type: SHA256

(2) 邏輯列配置加密器

只需要將加密器的名字改成上面聲明的encryptor_sha256即可,配置如下:

spring:
# Sharding-JDBC的配置
shardingsphere:
encrypt:
tables:
t_user:
columns:
# 邏輯列,sharding-jdbc中寫SQL需要用到的列
password:
# 存儲明文的字段
#plainColumn: password
# 存儲密文的字段
cipherColumn: cipher_pwd
# 指定加密器
encryptor: encryptor_sha256

至此,配置成功了,自己去演示看一下吧,這里就不再細(xì)說了。

2. QueryAssistedEncryptor 自定義實(shí)現(xiàn)

下面通過Base64加密算法自定義實(shí)現(xiàn)一個QueryAssistedEncryptor加密器,如下:

/**
* @author 不才陳某 公眾號:碼猿技術(shù)專欄
* 自定義QueryAssistedEncryptor加密器
*/
@Data
public class Base64AssistedEncryptor implements QueryAssistedEncryptor {

/**
* 別名,配置時需要
*/
public final static String ALGORITHM_NAME="Base64_Assisted";

private Properties properties = new Properties();

/**
* 輔助查詢列的加密方法
*/
@Override
public String queryAssistedEncrypt(String plaintext) {
if (null == plaintext) {
return null;
}
return Base64.encode(plaintext);
}

@Override
public void init() {

}

/**
* 加密方法
* 使用時間戳作為變動因子
*/
@Override
public String encrypt(final Object plaintext) {
if (null == plaintext) {
return null;
}
//獲取時間戳作為變動因子
String randomFactor =String.valueOf( new Date().getTime());
return Base64.encode(plaintext+"_"+randomFactor);
}

/**
* 解密方法
* Base64是一個可逆的加密算法,因此可以對密文進(jìn)行解密并且剔除變動因子則為明文
*/
@SneakyThrows
@Override
public Object decrypt(final String ciphertext) {
if (null == ciphertext) {
return null;
}
return new String(Base64.decode(ciphertext),"UTF-8").split("_")[0];
}

@Override
public String getType() {
return ALGORITHM_NAME;
}
}

需要注意以下兩點(diǎn):

  • queryAssistedEncrypt():該方法在插入、更新邏輯列設(shè)置輔助查詢列值、邏輯列作為where查詢條件時會被調(diào)用對輔助查詢列加密
  • decrypt():這里的Base64是可逆的加密算法,因此只需要對其解密,并且剔除變動因子則為明文

同樣的也需要在resource/META-INF/services目錄中新建一個org.apache.shardingsphere.encrypt.strategy.spi.Encryptor文件,內(nèi)容如下:

com.java.family.shardingjdbc003.encryptor.Base64AssistedEncryptor

配置也很簡單,同樣分為兩步,如下:

(1) 聲明加密器

配置如下:

spring:
# Sharding-JDBC的配置
shardingsphere:
encrypt:
encryptors:
# Base64加密算法,自定義的
encryptor_base64_assisted:
type: Base64_Assisted

(2) 邏輯列配置加密器

只需要將加密器的名字改成上面聲明的encryptor_base64_assisted即可,配置如下:

![33](https://java-family.cn/BlogImage/ShardingSphere/33.png)spring:
# Sharding-JDBC的配置
shardingsphere:
encrypt:
tables:
t_user:
columns:
# 邏輯列,sharding-jdbc中寫SQL需要用到的列
mobile:
# 密文存儲的列
cipherColumn: mobile
# 輔助查詢列,表中真實(shí)的字段名
assistedQueryColumn: mobile_data
encryptor: encryptor_base64_assisted

唯一不同的就是多了一個assistedQueryColumn輔助查詢列的配置。

好了,上述配置好了以后就可以進(jìn)行單元測試了,插入數(shù)據(jù)結(jié)果:

可以看到mobile這個字段的值都是不同的,但是mobile_data這個輔助查詢列都是相同的,因?yàn)檩o助查詢列并未使用變動因子進(jìn)行加密。

關(guān)于查詢?nèi)绻婕暗絤obile的條件查詢,那么將會調(diào)用queryAssistedEncrypt()方法加密后根據(jù)輔助查詢mobile_data列進(jìn)行查詢,SQL如下圖:


網(wǎng)站題目:聊聊Sharding-JDBC數(shù)據(jù)脫敏
轉(zhuǎn)載源于:http://www.5511xx.com/article/cohpdcj.html