spring-boot集成Apache ShardingSphere 5.0.0 感知
文章目录
一、前言
Apache ShardingSphere 通过对用户输入的 SQL 进行解析,并依据用户提供的加密规则对 SQL 进行改写,从而实现对原文数据进行加密,并将原文数据(可选)及密文数据同时存储到底层数据库。 在用户查询数据时,它仅从数据库中取出密文数据,并对其解密,最终将解密后的原始数据返回给用户。 Apache ShardingSphere 自动化 & 透明化了数据加密过程,让用户无需关注数据加密的实现细节,像使用普通数据那样使用加密数据。 此外,无论是已在线业务进行加密改造,还是新上线业务使用加密功能,Apache ShardingSphere 都可以提供一套相对完善的解决方案。
二、与spring-boot集成实现(数据加密)
1.建表语句
CREATE TABLE `t_encrypt` (
`id` varchar(36) COLLATE utf8_bin NOT NULL,
`phone_no_cipher` varchar(512) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
2.pom.xml
<properties>
<java.version>1.8</java.version>
<mybatis-plus.version>3.4.1</mybatis-plus.version>
<shardingsphere.version>5.0.0</shardingsphere.version>
</properties>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
3.application.yml
spring:
shardingsphere:
props:
sql-show: true
datasource:
ds0:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true
password: 123456
type: com.zaxxer.hikari.HikariDataSource
username: root
ds1:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true
password: 123456
type: com.zaxxer.hikari.HikariDataSource
username: root
names: ds0,ds1
rules:
encrypt:
encryptors:
custom-encrypt:
type: AES
props:
# 对称加密key(君不见黄河之水天上来,奔流到海不复回。)
aes-key-value: jbjhhzstsl,bldhbfh.
tables:
t_encrypt:
# 使用密文列查询(默认true)
query-with-cipher-column: true
columns:
phone_no:
# 逻辑列(虚拟列)
logic-column: phone_no
# 密文列(真实列)
cipher-column: phone_no_cipher
# 原文列(真实列,可选)
# plain-column: phone_no_plain
# 加密策略名称与上方对应(推荐使用短横线风格)
encryptor-name: custom-encrypt
mybatis-plus:
global-config:
db-config:
id-type: assign_id
内置的加密算法,
MD5
、AES
、RC4
;若准备自定义算法可参照数据加密,基于SPI机制自动扩展。不清楚SPI的原理,可以先阅读下源码分析-JDBC SPI加载机制。
4.CURD
- EncryptController.java
package com.example.demo.controller;
import com.example.demo.entity.Encrypt;
import com.example.demo.service.EncryptService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* (Encrypt)表控制层
*
* @author ouruyi
* @since 2021-12-14 17:29:10
*/
@RestController
@RequestMapping("/encrypt")
public class EncryptController {
/**
* 服务对象
*/
@Resource
private EncryptService encryptService;
@GetMapping("/{id}")
public Encrypt getById(@PathVariable String id) {
return this.encryptService.getById(id);
}
/**
* 通过手机号(明文)查询列表数据
* @param phoneNo 手机号
* @return 列表数据
*/
@GetMapping("/selectByPhoneNo/{phoneNo}")
public List<Encrypt> selectByPhoneNo(@PathVariable String phoneNo) {
return this.encryptService.selectByPhoneNo(phoneNo);
}
@GetMapping
public List<Encrypt> list() {
return this.encryptService.list();
}
@GetMapping("/count")
public Integer count() {
return this.encryptService.count();
}
@GetMapping("/mock")
public String mock() {
for (int i = 0; i < 12; i++) {
final Encrypt encrypt = new Encrypt();
encrypt.setPhoneNo(String.valueOf(i));
this.encryptService.save(encrypt);
}
return "SUCCESS";
}
}
- EncryptService.java
package com.example.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.Encrypt;
import java.util.List;
/**
* (Encrypt)表服务接口
*
* @author ouruyi
* @since 2021-12-14 17:29:10
*/
public interface EncryptService extends IService<Encrypt> {
List<Encrypt> selectByPhoneNo(String phoneNo);
}
- EncryptServiceImpl.java
package com.example.demo.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.dao.EncryptDao;
import com.example.demo.entity.Encrypt;
import com.example.demo.service.EncryptService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* (Encrypt)表服务实现类
*
* @author ouruyi
* @since 2021-12-14 17:29:10
*/
@Service("encryptService")
public class EncryptServiceImpl extends ServiceImpl<EncryptDao, Encrypt> implements EncryptService {
@Override
public List<Encrypt> selectByPhoneNo(String phoneNo) {
return this.baseMapper.selectList(new QueryWrapper<Encrypt>().lambda().eq(Encrypt::getPhoneNo, phoneNo));
}
}
- EncryptDao.java
package com.example.demo.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Encrypt;
/**
* (Encrypt)表数据库访问层
*
* @author ouruyi
* @since 2021-12-14 17:29:10
*/
public interface EncryptDao extends BaseMapper<Encrypt> {
}
- Encrypt.java
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.io.Serializable;
/**
* (Encrypt)表实体类
*
* @author ouruyi
* @since 2021-12-14 17:29:10
*/
@SuppressWarnings("serial")
@TableName("t_encrypt")
public class Encrypt extends Model<Encrypt> {
@TableId
private String id;
private String phoneNo;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
/**
* 获取主键值
*
* @return 主键值
*/
@Override
protected Serializable pkVal() {
return this.id;
}
}