diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 15401b66..268cb0ea 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -83,6 +83,7 @@ export default defineConfig({ {text: 'SQL 审计', link: '/zh/core/audit'}, {text: 'SQL 打印', link: '/zh/core/sql-print'}, {text: '多数据源', link: '/zh/core/multi-datasource'}, + {text: '数据源加密', link: '/zh/core/datasource-encryption'}, {text: '动态表名', link: '/zh/core/dynamic-table'}, {text: '事务管理', link: '/zh/core/tx'}, {text: '数据权限', link: '/zh/core/data-permission'}, diff --git a/docs/zh/core/datasource-encryption.md b/docs/zh/core/datasource-encryption.md new file mode 100644 index 00000000..174b42cc --- /dev/null +++ b/docs/zh/core/datasource-encryption.md @@ -0,0 +1,66 @@ +# 数据源加密 + +数据源加密指的是我们对数据库的链接信息进行加密,目前 MyBatis-Flex 支持加密的内容有 +- 数据源 URL +- 数据源用户名 +- 数据源用户密码 + +通过数据源加密功能,我们可以有效的保证数据库安全,减少数据盗用风险。 + +## 简介 + +在 MyBatis-Flex 中,我们并不关注数据库信息的加密方式,换一句话也就是说:**MyBatis-Flex 支持任何类型的加密方式**。 +在 MyBatis-Flex 中内置了一个名为 `DataSourceDecipher` 的接口,其作用是去解密用户配置的加密内容,从而真实的配置信息。 + +## 开始使用 +通过 `DataSourceManager` 配置 `DataSourceDecipher`。以下是示例代码: + +```java +DruidDataSource dataSource = new DruidDataSource(); +dataSource.setUrl("jdbc:mysql://localhost:3306/flex_test"); +dataSource.setUsername("root123"); // 真实的账号应该是 root +dataSource.setPassword("123456---0000"); // 真实的密码应该是 123456 + +//配置数据源解密器:DataSourceDecipher +DataSourceManager.setDecipher(new DataSourceDecipher() { + @Override + public String decrypt(DataSourceProperty property, String value) { + //解密用户名,通过编码支持任意加密方式的解密 + if (property == DataSourceProperty.USERNAME) { + return value.substring(0, 4); + } + //解密密码 + else if (property == DataSourceProperty.PASSWORD) { + return value.substring(0, 6); + } + return value; + } +}); + +MybatisFlexBootstrap.getInstance() + .setDataSource(dataSource) + .addMapper(TenantAccountMapper.class) + .start(); + +List rowList = Db.selectAll("tb_account"); +RowUtil.printPretty(rowList); +``` + +> 需要注意的是:`DataSourceManager.setDecipher()` 的配置,需要在 MyBatis-Flex 初始化之前进行。 + + +## SpringBoot 支持 +在 SpringBoot 项目下,直接通过 `@Configuration` 即可使用: + +```java +@Configuration +public class MyConfiguration { + + @Bean + public DataSourceDecipher decipher(){ + DataSourceDecipher decipher = new ....; + return decipher; + } + +} +``` \ No newline at end of file diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java index 689ac882..3da0eea3 100644 --- a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java +++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java @@ -16,9 +16,12 @@ package com.mybatisflex.spring.boot; import com.mybatisflex.core.datasource.DataSourceBuilder; +import com.mybatisflex.core.datasource.DataSourceDecipher; +import com.mybatisflex.core.datasource.DataSourceManager; import com.mybatisflex.core.datasource.FlexDataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -42,10 +45,12 @@ import java.util.Map; public class MultiDataSourceAutoConfiguration { private final Map> dataSourceProperties; + protected final DataSourceDecipher dataSourceDecipher; - - public MultiDataSourceAutoConfiguration(MybatisFlexProperties properties) { + public MultiDataSourceAutoConfiguration(MybatisFlexProperties properties + , ObjectProvider dataSourceDecipherProvider) { dataSourceProperties = properties.getDatasource(); + dataSourceDecipher = dataSourceDecipherProvider.getIfAvailable(); } @@ -53,6 +58,10 @@ public class MultiDataSourceAutoConfiguration { @ConditionalOnMissingBean public DataSource dataSource() { + if (dataSourceDecipher != null) { + DataSourceManager.setDecipher(dataSourceDecipher); + } + FlexDataSource flexDataSource = null; if (dataSourceProperties != null && !dataSourceProperties.isEmpty()) { diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java index fd55c548..84b24219 100644 --- a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java +++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java @@ -16,6 +16,8 @@ package com.mybatisflex.spring.boot; import com.mybatisflex.core.FlexGlobalConfig; +import com.mybatisflex.core.datasource.DataSourceDecipher; +import com.mybatisflex.core.datasource.DataSourceManager; import com.mybatisflex.core.mybatis.FlexConfiguration; import com.mybatisflex.spring.FlexSqlSessionFactoryBean; import org.apache.ibatis.annotations.Mapper; @@ -104,11 +106,15 @@ public class MybatisFlexAutoConfiguration implements InitializingBean { protected final List sqlSessionFactoryBeanCustomizers; + protected final DataSourceDecipher dataSourceDecipher; + + public MybatisFlexAutoConfiguration(MybatisFlexProperties properties, ObjectProvider interceptorsProvider, ObjectProvider typeHandlersProvider, ObjectProvider languageDriversProvider, ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, ObjectProvider> configurationCustomizersProvider, - ObjectProvider> sqlSessionFactoryBeanCustomizers) { + ObjectProvider> sqlSessionFactoryBeanCustomizers, + ObjectProvider dataSourceDecipherProvider) { this.properties = properties; this.interceptors = interceptorsProvider.getIfAvailable(); this.typeHandlers = typeHandlersProvider.getIfAvailable(); @@ -117,6 +123,9 @@ public class MybatisFlexAutoConfiguration implements InitializingBean { this.databaseIdProvider = databaseIdProvider.getIfAvailable(); this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable(); this.sqlSessionFactoryBeanCustomizers = sqlSessionFactoryBeanCustomizers.getIfAvailable(); + + //数据密码 + this.dataSourceDecipher = dataSourceDecipherProvider.getIfAvailable(); } @Override @@ -138,6 +147,9 @@ public class MybatisFlexAutoConfiguration implements InitializingBean { @Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { + if (dataSourceDecipher != null) { + DataSourceManager.setDecipher(dataSourceDecipher); + } SqlSessionFactoryBean factory = new FlexSqlSessionFactoryBean(); factory.setDataSource(dataSource); if (properties.getConfiguration() == null || properties.getConfiguration().getVfsImpl() == null) { diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/MyConfigurationCustomizer.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/MyConfigurationCustomizer.java index 75dfb913..e5ab0a97 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/MyConfigurationCustomizer.java +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/MyConfigurationCustomizer.java @@ -1,8 +1,11 @@ package com.mybatisflex.test; +import com.mybatisflex.core.datasource.DataSourceDecipher; +import com.mybatisflex.core.datasource.DataSourceProperty; import com.mybatisflex.core.mybatis.FlexConfiguration; import com.mybatisflex.spring.boot.ConfigurationCustomizer; import org.apache.ibatis.logging.stdout.StdOutImpl; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @@ -13,4 +16,16 @@ public class MyConfigurationCustomizer implements ConfigurationCustomizer { System.out.println(">>>>>>> MyConfigurationCustomizer.customize() invoked"); configuration.setLogImpl(StdOutImpl.class); } + + @Bean + public DataSourceDecipher decipher(){ + DataSourceDecipher decipher = new DataSourceDecipher() { + @Override + public String decrypt(DataSourceProperty property, String value) { + System.out.println(">>>>>> decipher.decrypt"); + return value; + } + }; + return decipher; + } }