A spring-boot starter to encrypt and decrypt some column of database
Tips: For running test application I recommend you to set the correct path that you can get a cleanning project directory.
- Set value of
spring.datasource.url
spring: datasource: embedded-database-connection: h2 driver-class-name: org.h2.Driver #url: jdbc:h2:mem:h2;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE url: jdbc:h2:/Users/weasley/Development/IdeaProjects/mybatis-encrypt-spring-boot-parent/mybatis-encrypt-spring-boot-tests/h2;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE username: "" password: ""
- Set value for
alphahub.dtt.all-in-one-table.filepathandalphahub.dtt.code-generator.module-path
alphahub: dtt: show-sql: on all-in-one-table: enable: true filename: all_in_one.sql filepath: /Users/weasley/Downloads code-generator: is-enable: on include-controller: on include-interface: on override-exists: off remove-prefix: dtt base-classes: - com.example.demain.DttMember module-name: example module-package: com.example module-path: /Users/weasley/Development/IdeaProjects/mybatis-encrypt-spring-boot-parent/mybatis-encrypt-spring-boot-tests
<!-- mybatis-encrypt --> <dependency> <groupId>io.github.weasley-j</groupId> <artifactId>mybatis-encrypt-spring-boot-starter</artifactId> <version>1.0.3</version> </dependency>
MyBatis encryption configuration,2 algorithms embeded. you can choose one of them. Or you can implement you own algorithm.
# mybatis encryption configuration mybatis: encrypt: enable: on encrypt-type: base64
Replace your own key and keyIv
# mybatis encryption configuration mybatis: encrypt: enable: on encrypt-type: aes aes: key: Jidkdp1mWL1tRyK= key-iv: Poikdp1mWL1jijK=
As you choose encrypt-type = diy,you must implement io.github.weasleyj.mybatis.encrypt.core.EncryptStrategy to define your own algorithms for encryption and decryption some column of database,
# mybatis encryption configuration mybatis: encrypt: enable: on encrypt-type: diy diy: encrypt-strategy: com.somepackage.YourEncryptStrategyImpl
3 Use @EnableMybatisEncryption annotation to annotate a Bean of your application that Spring AOC can find it
- Annotate on Java configuration class
import io.github.weasleyj.mybatis.encrypt.annotation.EnableMybatisEncryption; import org.springframework.context.annotation.Configuration; /** * Mybatis Encrypt Configuration class * * @author weasley * @version 1.0.0 */ @Configuration @EnableMybatisEncryption public class MybatisEncryptConfig { }
- Annotate on your SpringBoot aplciation Main class
import io.github.weasleyj.mybatis.encrypt.annotation.EnableMybatisEncryption; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Some application Main class */ @SpringBootApplication @EnableMybatisEncryption public class SomeApplication { public static void main(String[] args) { SomeApplication.run(SomeApplication.class, args); } }
- Use
@Encryptionannotate on the field property which you need encryption and decryption,Here is an example to decrypt and encryptnickname:
API link: http://localhost:8080/api/member/save/direct
import com.baomidou.mybatisplus.annotation.TableId; import io.github.weasleyj.mybatis.encrypt.annotation.Encryption; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; /** * 用户信息 */ @Data @Builder @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) public class DttMember implements Serializable { /** * 主键id * * @primaryKey */ @TableId private Long memberId; /** * 用户openId * * @defaultValue e1be63305 * @length 16 */ private String openId; /** * 用户昵称 * * @length 32 */ @Encryption private String nickname; /** * 是否启用, 默认:1 * * @defaultValue true */ private Boolean isEnable; /** * 用户积分余额, 默认:0.00 * * @precision 10 * @scale 4 * @defaultValue 0.01 */ private BigDecimal balance; /** * 出生日期,格式:yyyy-MM-dd HH:mm:ss */ private LocalDateTime birthday; /** * 用户状态;0 正常(默认),1 已冻结,2 账号已封,3 账号异常 * * @defaultValue 3 */ private Integer status; /** * 账户注销状态;0 未注销(默认),1 已销户 * * @defaultValue 1 * @dbDataType SMALLINT */ private Integer deleted; /** * 注册时间,格式: yyyy-MM-dd */ private LocalDate registrarDate; /** * 会员加速开始时间, 格式:HH:mm:ss */ private LocalTime accelerateBeginTime; /** * 会员加速结束时间, 格式:HH:mm:ss */ private LocalTime accelerateEndTime; /** * 修改时间 */ private LocalDateTime updateTime; }
- When sql with type of
INSERT,UPDATEExecuted byMyBatisExecutor,nicknamewill be encrypted, i.e:
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69693f7a]
JDBC Connection [HikariProxyConnection@1043294096 wrapping conn1: url=jdbc:h2:/Users/weasley/Development/IdeaProjects/mybatis-encrypt-spring-boot-parent/mybatis-encrypt-spring-boot-tests/h2 user=] will be managed by Spring
==> Preparing: SELECT MAX(member_id) memberId FROM dtt_member
==> Parameters:
<== Columns: MEMBERID
<== Row: 5
<== Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69693f7a]
2022年12月20日 17:30:27.737 INFO 15312 --- [nio-8080-exec-1] com.example.controller.MemberController : {"memberId":6,"openId":"fawezOE5sT","nickname":"蒋震南","isEnable":true,"balance":865,"birthday":"2022-12-20 17:30:27","status":0,"deleted":1,"registrarDate":"2022-12-20","accelerateBeginTime":"17:30:27","accelerateEndTime":"17:30:27","updateTime":"2022-12-20 17:30:27"}
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69693f7a] from current transaction
2022年12月20日 17:30:27.822 DEBUG 15312 --- [nio-8080-exec-1] w.m.e.i.DefaultMybatisEncryptInterceptor : Encrypt field for 'nickname', Plaintext: 蒋震南, Ciphertext: IgaLfu2eBut5jAKENLZd3A==
==> Preparing: INSERT INTO dtt_member ( member_id, open_id, nickname, is_enable, balance, birthday, status, deleted, registrar_date, accelerate_begin_time, accelerate_end_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 6(Long), fawezOE5sT(String), IgaLfu2eBut5jAKENLZd3A==(String), true(Boolean), 865(BigDecimal), 2022年12月20日T17:30:27.558(LocalDateTime), 0(Integer), 1(Integer), 2022年12月20日(LocalDate), 17:30:27.558(LocalTime), 17:30:27.558(LocalTime), 2022年12月20日T17:30:27.558(LocalDateTime)
<== Updates: 1
Real SQL:
INSERT INTO dtt_member ( member_id, open_id, nickname, is_enable, balance, birthday, status, deleted, registrar_date, accelerate_begin_time, accelerate_end_time, update_time ) VALUES ( 6, 'fawezOE5sT', 'IgaLfu2eBut5jAKENLZd3A==', true, 865, '2022年12月20日T17:30:27.558', 0, 1, '2022年12月20日', '17:30:27.558', '17:30:27.558', '2022年12月20日T17:30:27.558' );
- When sql with type of
SELECTExecuted byMyBatisExecutor,nicknamewill be decrypted, i.e:
API link: http://localhost:8080/api/member/page/pagehelper?pageNum=1&pageSize=10
JDBC Connection [HikariProxyConnection@670142194 wrapping conn1: url=jdbc:h2:/Users/weasley/Development/IdeaProjects/mybatis-encrypt-spring-boot-parent/mybatis-encrypt-spring-boot-tests/h2 user=] will not be managed by Spring
==> Preparing: SELECT count(0) FROM dtt_member
==> Parameters:
<== Columns: COUNT(*)
<== Row: 6
<== Total: 1
==> Preparing: SELECT member_id,open_id,nickname,is_enable,balance,birthday,status,deleted,registrar_date,accelerate_begin_time,accelerate_end_time,update_time FROM dtt_member LIMIT ?
==> Parameters: 10(Integer)
<== Columns: MEMBER_ID, OPEN_ID, NICKNAME, IS_ENABLE, BALANCE, BIRTHDAY, STATUS, DELETED, REGISTRAR_DATE, ACCELERATE_BEGIN_TIME, ACCELERATE_END_TIME, UPDATE_TIME
<== Row: 1, fawezOE5sT, IgaLfu2eBut5jAKENLZd3A==, TRUE, 865.0000, 2022年12月20日 13:33:46.547, 0, 1, 2022年12月20日, 13:33:47, 13:33:47, 2022年12月20日 13:33:46.547
<== Row: 2, fawezOE5sT, IgaLfu2eBut5jAKENLZd3A==, TRUE, 865.0000, 2022年12月20日 13:33:49.226, 0, 1, 2022年12月20日, 13:33:49, 13:33:49, 2022年12月20日 13:33:49.226
<== Row: 3, fawezOE5sT, IgaLfu2eBut5jAKENLZd3A==, TRUE, 865.0000, 2022年12月20日 13:33:50.398, 0, 1, 2022年12月20日, 13:33:50, 13:33:50, 2022年12月20日 13:33:50.398
<== Row: 4, fawezOE5sT, IgaLfu2eBut5jAKENLZd3A==, TRUE, 865.0000, 2022年12月20日 13:33:51.319, 0, 1, 2022年12月20日, 13:33:51, 13:33:51, 2022年12月20日 13:33:51.319
<== Row: 5, fawezOE5sT, IgaLfu2eBut5jAKENLZd3A==, TRUE, 865.0000, 2022年12月20日 13:33:52.31, 0, 1, 2022年12月20日, 13:33:52, 13:33:52, 2022年12月20日 13:33:52.31
<== Row: 6, fawezOE5sT, IgaLfu2eBut5jAKENLZd3A==, TRUE, 865.0000, 2022年12月20日 17:30:27.558, 0, 1, 2022年12月20日, 17:30:28, 17:30:28, 2022年12月20日 17:30:27.558
<== Total: 6
2022年12月20日 17:45:12.534 DEBUG 15634 --- [nio-8080-exec-1] w.m.e.i.DefaultMybatisEncryptInterceptor : Decrypt field for 'nickname', Ciphertext: IgaLfu2eBut5jAKENLZd3A==, Plaintext: 蒋震南
2022年12月20日 17:45:12.534 DEBUG 15634 --- [nio-8080-exec-1] w.m.e.i.DefaultMybatisEncryptInterceptor : Decrypt field for 'nickname', Ciphertext: IgaLfu2eBut5jAKENLZd3A==, Plaintext: 蒋震南
2022年12月20日 17:45:12.534 DEBUG 15634 --- [nio-8080-exec-1] w.m.e.i.DefaultMybatisEncryptInterceptor : Decrypt field for 'nickname', Ciphertext: IgaLfu2eBut5jAKENLZd3A==, Plaintext: 蒋震南
2022年12月20日 17:45:12.535 DEBUG 15634 --- [nio-8080-exec-1] w.m.e.i.DefaultMybatisEncryptInterceptor : Decrypt field for 'nickname', Ciphertext: IgaLfu2eBut5jAKENLZd3A==, Plaintext: 蒋震南
2022年12月20日 17:45:12.535 DEBUG 15634 --- [nio-8080-exec-1] w.m.e.i.DefaultMybatisEncryptInterceptor : Decrypt field for 'nickname', Ciphertext: IgaLfu2eBut5jAKENLZd3A==, Plaintext: 蒋震南
2022年12月20日 17:45:12.535 DEBUG 15634 --- [nio-8080-exec-1] w.m.e.i.DefaultMybatisEncryptInterceptor : Decrypt field for 'nickname', Ciphertext: IgaLfu2eBut5jAKENLZd3A==, Plaintext: 蒋震南
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4b849667]
SQL
SELECT member_id,open_id,nickname,is_enable,balance,birthday,status,deleted,registrar_date,accelerate_begin_time,accelerate_end_time,update_time FROM dtt_member LIMIT 10;
Finally, you can get some results like this:
{
"pageNum": 1,
"pageSize": 10,
"total": 6,
"pages": 1,
"list": [
{
"memberId": 1,
"openId": "fawezOE5sT",
"nickname": "蒋震南",
"isEnable": true,
"balance": 865.0000,
"birthday": "2022年12月20日T13:33:46.547",
"status": 0,
"deleted": 1,
"registrarDate": "2022年12月20日",
"accelerateBeginTime": "13:33:47",
"accelerateEndTime": "13:33:47",
"updateTime": "2022年12月20日T13:33:46.547"
},
{
"memberId": 2,
"openId": "fawezOE5sT",
"nickname": "蒋震南",
"isEnable": true,
"balance": 865.0000,
"birthday": "2022年12月20日T13:33:49.226",
"status": 0,
"deleted": 1,
"registrarDate": "2022年12月20日",
"accelerateBeginTime": "13:33:49",
"accelerateEndTime": "13:33:49",
"updateTime": "2022年12月20日T13:33:49.226"
},
{
"memberId": 3,
"openId": "fawezOE5sT",
"nickname": "蒋震南",
"isEnable": true,
"balance": 865.0000,
"birthday": "2022年12月20日T13:33:50.398",
"status": 0,
"deleted": 1,
"registrarDate": "2022年12月20日",
"accelerateBeginTime": "13:33:50",
"accelerateEndTime": "13:33:50",
"updateTime": "2022年12月20日T13:33:50.398"
},
{
"memberId": 4,
"openId": "fawezOE5sT",
"nickname": "蒋震南",
"isEnable": true,
"balance": 865.0000,
"birthday": "2022年12月20日T13:33:51.319",
"status": 0,
"deleted": 1,
"registrarDate": "2022年12月20日",
"accelerateBeginTime": "13:33:51",
"accelerateEndTime": "13:33:51",
"updateTime": "2022年12月20日T13:33:51.319"
},
{
"memberId": 5,
"openId": "fawezOE5sT",
"nickname": "蒋震南",
"isEnable": true,
"balance": 865.0000,
"birthday": "2022年12月20日T13:33:52.31",
"status": 0,
"deleted": 1,
"registrarDate": "2022年12月20日",
"accelerateBeginTime": "13:33:52",
"accelerateEndTime": "13:33:52",
"updateTime": "2022年12月20日T13:33:52.31"
},
{
"memberId": 6,
"openId": "fawezOE5sT",
"nickname": "蒋震南",
"isEnable": true,
"balance": 865.0000,
"birthday": "2022年12月20日T17:30:27.558",
"status": 0,
"deleted": 1,
"registrarDate": "2022年12月20日",
"accelerateBeginTime": "17:30:28",
"accelerateEndTime": "17:30:28",
"updateTime": "2022年12月20日T17:30:27.558"
}
]
}Exclude LIKE SQL grammar
- You can use this
APIEncryptStrategy#convertto convert your plain bean as a cipher bean (Only converts the field annotated by annotation@Encryption), Here is an Example that you can reference.