背景:
對於用戶的個人敏感信息,如密碼、身份證號、家庭住址等信息,在進行存儲數據庫之前,都需要進行加密。使得即使存入數據庫之後,數據庫的管理員看到的數據也是加密的。這一過程叫做數據脫敏。
一些安全框架如shiro、spring security都提供了加密的手段。這裏ShardingJdbc也提供了內置的加密方式,MD5、AES。
關於數據脫敏的詳細文檔參考官方數據脫敏部分
配置:
這裏使用前兩篇的配置(數據分片、讀寫分離)基礎上再加上數據脫敏配置
server:
port: 8999
spring:
application:
name: mybatis-demo
shardingsphere:
datasource:
# 數據庫的別名
names: ds0,ds1,ds0-slave0,ds0-slave1
# 主庫1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/dhb?serverTimezone=UTC
password: 12345
username: root
# 主庫1的從庫1
ds0-slave0:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3307/dhb?serverTimezone=UTC
password: 12345
username: root
# 主庫1的從庫2
ds0-slave1:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3308/dhb?serverTimezone=UTC
password: 12345
username: root
# 主庫2
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3310/dhb?serverTimezone=UTC
password: 12345
username: root
# 數據分片配置---start
sharding:
# 默認分庫策略
default-database-strategy:
inline:
sharding-column: id
algorithm-expression: ds$->{id % 2}
# 默認分表策略
default-table-strategy:
inline:
sharding-column: age
algorithm-expression: user_$->{age % 2}
# 數據節點
tables:
user:
actual-data-nodes: ds$->{0..1}.user_$->{0..1}
# 默認數據庫
default-data-source-name: ds0
# 數據分片配置---end
# 讀寫分離配置---start
master-slave-rules:
ds0:
master-data-source-name: ds0
slave-data-source-names: ds0-slave0,ds0-slave1
#從庫負載均衡算法類型,可選值:ROUND_ROBIN,RANDOM。
#若`load-balance-algorithm-class-name`存在則忽略該配置
load-balance-algorithm-type: ROUND_ROBIN
#從庫負載均衡算法類名稱。該類需實現MasterSlaveLoadBalanceAlgorithm接口且提供無參數構造器
#load-balance-algorithm-class-name=
# 讀寫分離配置---end
# 數據脫敏規則配置---start
encrypt-rule:
encryptors:
encryptor_aes:
# 加密、解密器的名字,內置的爲MD5,aes.
# 可以自定義,實現
# org.apache.shardingsphere.encrypt.strategy.spi.Encryptor
# 或者
# org.apache.shardingsphere.encrypt.strategy.spi.QueryAssistedEncryptor
# 這兩個接口即可
type: aes
props:
aes.key.value: 123456abc
tables:
# 數據庫,對應上面分片的tables
user:
columns:
# 邏輯列,就是寫SQL裏面的列,因爲實體類的名字和數據庫的加密列一致,所以這裏都是name
name:
# 密文列,用來存儲密文數據
cipherColumn: name
# 加密器名字
encryptor: encryptor_aes
# 數據脫敏規則配置---end
props:
# 打印SQL
sql.show: true
check:
table:
metadata: true
# 是否在啓動時檢查分表元數據一致性
enabled: true
query:
with:
cipher:
column: true
aop:
proxy-target-class: false
# 因爲Druid數據源和默認的數據源衝突,添加此配置
main:
allow-bean-definition-overriding: true
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-not-delete-value: 0
logic-delete-value: 1
mapper-locations: classpath:/mapper/*.xml
typeAliasesPackage: com.example.mybatis.demomybatis.entity
測試:
1、插入一條數據
可以看到,根據之前的分片規則,將這條數據路由到ds1(3310實例)的user_1表中,並且插入之前,將name字段進行加密了
2、查詢剛剛插入的數據
可以看到,查詢出來的name也是被解密的。這樣數據脫敏就完成了。
問題1:這裏爲什麼查詢了四張表?
回答:因爲前面文章配置的數據分片,是id(分庫策略)、age(分表策略),而查詢name屬性並沒有配置爲分片鍵,這時候會進行全路由即查詢所有表,實際生產環境萬萬不可這樣寫
問題2:既然是全路由,不是一共配置了八張表(每個數據庫下都要user_0,user_1兩張表)嗎,爲什麼查了四張表?
回答:因爲前面文章配置的讀寫分離(ds0-slave0、ds0-slave1)是ds的從庫,默認讀寫分離是讀都走從庫,所以這裏應該是兩個從庫+一個主庫,應該是6張表,但是這裏卻是四張表。這裏我確實是有疑惑,已經在GitHub上提了問題,看看官方會不會解答一下。
文章涉及到的代碼、配置已經全部放到GitHub上了,如有需要,自取。地址
6月1日更新:
官方已經回覆了,全路由是對於分片而言的,如果數據分片+主從架構 這種場景下,在不同的數據庫下相同的表名,則被視爲同一張表