Skip to content

Commit

Permalink
feat: database config and fragment variable encrypt (DataLinkDC#2178)
Browse files Browse the repository at this point in the history
* feat: database config and fragment variable encrypt

* Update db-h2.sql dinky_database table password column
  • Loading branch information
ruanjf authored Aug 8, 2023
1 parent 7f8134e commit 7420707
Show file tree
Hide file tree
Showing 17 changed files with 426 additions and 8 deletions.
4 changes: 4 additions & 0 deletions dinky-admin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
</properties>

<dependencies>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,14 @@ public Result<Void> saveOrUpdate(@RequestBody DataBase database) {
@Log(title = "DataBase Get All", businessType = BusinessType.QUERY)
@ApiOperation("DataBase Get All")
public ProTableResult<DataBase> listDataBases(@RequestBody JsonNode para) {
return databaseService.selectForProTable(para);
final ProTableResult<DataBase> result = databaseService.selectForProTable(para);
// 密码不返回
if (result != null && result.getData() != null) {
for (DataBase data : result.getData()) {
data.setPassword(null);
}
}
return result;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.dinky.data.result.ProTableResult;
import org.dinky.data.result.Result;
import org.dinky.service.FragmentVariableService;
import org.dinky.utils.FragmentVariableUtils;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -81,7 +82,17 @@ public Result<Void> saveOrUpdate(@RequestBody FragmentVariable fragmentVariable)
@Log(title = "FragmentVariable List", businessType = BusinessType.QUERY)
@ApiOperation("FragmentVariable List")
public ProTableResult<FragmentVariable> listFragmentVariable(@RequestBody JsonNode para) {
return fragmentVariableService.selectForProTable(para);
final ProTableResult<FragmentVariable> result =
fragmentVariableService.selectForProTable(para);
// 敏感值不返回
if (result != null && result.getData() != null) {
for (FragmentVariable variable : result.getData()) {
if (FragmentVariableUtils.isSensitive(variable.getName())) {
variable.setFragmentValue(null);
}
}
}
return result;
}

/**
Expand Down
57 changes: 57 additions & 0 deletions dinky-admin/src/main/java/org/dinky/crypto/CryptoComponent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.dinky.crypto;

import org.jasypt.util.text.AES256TextEncryptor;
import org.springframework.stereotype.Component;

@Component
public class CryptoComponent {

private final boolean enabled;
private final AES256TextEncryptor textEncryptor;

public CryptoComponent(CryptoProperties cryptoProperties) {
this.enabled = cryptoProperties.getEnabled();
this.textEncryptor = new AES256TextEncryptor();
if (cryptoProperties.getEncryptionPassword() != null) {
this.textEncryptor.setPassword(cryptoProperties.getEncryptionPassword());
}
}

public String encryptText(String result) {
if (!enabled) {
return result;
}

return textEncryptor.encrypt(result);
}

public String decryptText(String result) {
if (!enabled) {
return result;
}

if (result == null) {
return null;
}
return textEncryptor.decrypt(result);
}
}
37 changes: 37 additions & 0 deletions dinky-admin/src/main/java/org/dinky/crypto/CryptoProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.dinky.crypto;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@ConfigurationProperties(prefix = "crypto")
@Component
public class CryptoProperties {
/** 是否启用加解密配置 */
private Boolean enabled = false;
/** 加密密钥 */
private String encryptionPassword;
}
6 changes: 5 additions & 1 deletion dinky-admin/src/main/java/org/dinky/data/model/DataBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
package org.dinky.data.model;

import org.dinky.metadata.driver.DriverConfig;
import org.dinky.mybatis.crypto.CryptoTypeHandler;
import org.dinky.mybatis.model.SuperEntity;

import java.time.LocalDateTime;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;
Expand All @@ -36,7 +38,7 @@
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("dinky_database")
@TableName(value = "dinky_database", autoResultMap = true)
public class DataBase extends SuperEntity {

private static final long serialVersionUID = -5002272138861566408L;
Expand All @@ -47,6 +49,8 @@ public class DataBase extends SuperEntity {
private String type;
private String url;
private String username;

@TableField(typeHandler = CryptoTypeHandler.class)
private String password;

private String note;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.dinky.mybatis.crypto;

import org.dinky.context.SpringContextUtils;
import org.dinky.crypto.CryptoComponent;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class CryptoTypeHandler extends BaseTypeHandler<String> {

private final CryptoComponent cryptoComponent;

public CryptoTypeHandler() {
cryptoComponent = SpringContextUtils.getBeanByClass(CryptoComponent.class);
}

@Override
public void setNonNullParameter(
PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, encryptText(parameter));
}

@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return decryptText(rs.getString(columnName));
}

@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return decryptText(rs.getString(columnIndex));
}

@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return decryptText(cs.getString(columnIndex));
}

private String encryptText(String result) {
return cryptoComponent.encryptText(result);
}

private String decryptText(String result) {
return cryptoComponent.decryptText(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.dinky.mybatis.crypto;

import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.autoconfigure.SqlSessionFactoryBeanCustomizer;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;

@Component
public class MybatisPlusCustomizer implements SqlSessionFactoryBeanCustomizer {

@Override
public void customize(MybatisSqlSessionFactoryBean factoryBean) {
factoryBean.setConfiguration(
new MybatisConfiguration() {
@Override
public void addMappedStatement(MappedStatement ms) {
final String ns = ms.getId().replaceAll("(.*Mapper)\\.\\w+$", "$1");
final MapperBuilderAssistant builderAssistant =
new MapperBuilderAssistant(ms.getConfiguration(), "");
builderAssistant.setCurrentNamespace(ns);
boolean[] changes = new boolean[] {false};
final List<ResultMap> collect =
ms.getResultMaps().stream()
.map(
m -> {
// 仅ResultType为Table且包含TypeHandler时,替换ResultMap为MybatisPlus生成的
TableName table =
m.getType()
.getAnnotation(TableName.class);
if (table != null) {
TableInfo tableInfo =
TableInfoHelper.getTableInfo(
m.getType());
if (tableInfo == null) {
tableInfo =
TableInfoHelper.initTableInfo(
builderAssistant,
m.getType());
}
if (tableInfo != null
&& tableInfo.getResultMap() != null
&& tableInfo.getFieldList().stream()
.anyMatch(
f ->
f
.getTypeHandler()
!= null)) {
ResultMap resultMap =
ms.getConfiguration()
.getResultMap(
tableInfo
.getResultMap());
if (resultMap != null
&& resultMap != m) {
changes[0] = true;
return resultMap;
}
}
}
return m;
})
.collect(Collectors.toList());
if (changes[0]) {
final Field field =
ReflectionUtils.findField(ms.getClass(), "resultMaps");
if (field != null) {
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(
field, ms, Collections.unmodifiableList(collect));
}
}
super.addMappedStatement(ms);
}
});
}
}
Loading

0 comments on commit 7420707

Please sign in to comment.