首页 > 数据库 >数据库敏感字段加解密便捷方式

数据库敏感字段加解密便捷方式

时间:2023-09-01 17:44:25浏览次数:60  
标签:String 便捷 spring 数据库 加解密 druid private datasource import

因为项目临时新加需求对数据库的敏感字段加解密,需要对项目的整体代码进行修改,可愁怀我了

在网上发现有注解的方式可以进行针对字段加解密,感兴趣的可以去看原作者的文章https://blog.csdn.net/u012954706/article/details/105437768#comments

我这里只是留下备档防止文章不见了,你们看起来会很难受,所以看大佬的文章吧

1、数据库连接加解密

1.1、数据库连接配置

####################################

### DB

####################################

#durid

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.druid.initialSize=5

spring.datasource.druid.minIdle=5

spring.datasource.druid.maxActive=20

spring.datasource.druid.maxWait=60000

spring.datasource.druid.timeBetweenEvictionRunsMillis=60000

spring.datasource.druid.minEvictableIdleTimeMillis=300000

spring.datasource.druid.validationQuery=SELECT 1 FROM DUAL

spring.datasource.druid.testWhileIdle=true

spring.datasource.druid.testOnBorrow=false

spring.datasource.druid.testOnReturn=false

 

 

 

#####################################

#### DB

####################################

spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/hlj_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true

spring.datasource.druid.username=GCBeAUOZNANpmXfIUPO42qx/dQP80Lae3BI7ABxQN2AzWhgQAG+S6Dhe

spring.datasource.druid.password=GCAfE1p20be+BX5TZsVlFe1/T1bQ+f2IhnjqOQKe7CJT7xgQ8YOQrf7U

####################################

 

 

 

#是否需要数据连接加密

spring.datasource.encrypt=true

1.2、Java数据库连接

package com.fintech.confin.web.config;

 

import com.alibaba.druid.pool.DruidDataSource;

import com.fintech.confin.sensitivity.KeycenterUtils;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

import javax.sql.DataSource;

 

/**

 * @author HealerJean

 * @ClassName DateSourceConfig

 * @date 2020/4/9  10:43.

 * @Description

 */

@Configuration

public class DateSourceConfig {

 

 

@Value("${spring.datasource.druid.driver-class-name}")

private String driverClassName;

@Value("${spring.datasource.druid.url}")

private String dbUrl;

@Value("${spring.datasource.druid.username}")

private String username;

@Value("${spring.datasource.druid.password}")

private String password;

@Value("${spring.datasource.druid.initialSize}")

private int initialSize;

@Value("${spring.datasource.druid.minIdle}")

private int minIdle;

@Value("${spring.datasource.druid.maxActive}")

private int maxActive;

@Value("${spring.datasource.druid.maxWait}")

private int maxWait;

@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")

private int timeBetweenEvictionRunsMillis;

@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")

private int minEvictableIdleTimeMillis;

@Value("${spring.datasource.druid.validationQuery}")

private String validationQuery;

@Value("${spring.datasource.druid.testWhileIdle}")

private boolean testWhileIdle;

@Value("${spring.datasource.druid.testOnBorrow}")

private boolean testOnBorrow;

@Value("${spring.datasource.druid.testOnReturn}")

private boolean testOnReturn;

@Value("${spring.datasource.encrypt}")

private boolean encrypt;

 

@Bean(name = "dataSource")

public DataSource dataSource(KeycenterUtils keycenterUtils) {

DruidDataSource datasource = new DruidDataSource();

datasource.setDriverClassName(driverClassName);

datasource.setUrl(dbUrl);

if (encrypt) {

datasource.setUsername(keycenterUtils.decrypt(username));

datasource.setPassword(keycenterUtils.decrypt(password));

} else {

datasource.setUsername(username);

datasource.setPassword(password);

}

datasource.setInitialSize(initialSize);

datasource.setMinIdle(minIdle);

datasource.setMaxActive(maxActive);

datasource.setMaxWait(maxWait);

datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);

datasource.setValidationQuery(validationQuery);

datasource.setTestWhileIdle(testWhileIdle);

datasource.setTestOnBorrow(testOnBorrow);

datasource.setTestOnReturn(testOnReturn);

return datasource;

}

 

}

2、数据库字段加解密

2.1、KeyCenterUtils:加解密工具类

package com.healerjean.proj.config.keycenter.one;

 

import org.springframework.stereotype.Service;

 

import java.util.Base64;

 

/**

 * @author HealerJean

 * @ClassName AES

 * @date 2020/4/9  14:28.

 * @Description

 */

@Service

public class KeyCenterUtils {

 

    /**

     * 自己写加密逻辑

     */

    public  String encrypt(String src) {

        try {

            String result = Base64.getEncoder().encodeToString(src.getBytes("UTF-8"));

            return result;

        } catch (Exception e) {

            throw new RuntimeException("encrypt fail!", e);

        }

    }

 

    /**

     * 自己写解密逻辑

     */

    public  String decrypt(String src) {

        try {

            byte[] asBytes = Base64.getDecoder().decode(src);

            String result = new String(asBytes, "UTF-8");

            return result;

        } catch (Exception e) {

            throw new RuntimeException("decrypt fail!", e);

        }

    }

 

}

2.2、CustomTypeHandler数据库字段加解密控制器

package com.healerjean.proj.config.keycenter.one;

 

/**

 * @author HealerJean

 * @ClassName AESTypeHandler

 * @date 2020/4/9  14:27.

 * @Description

 */

 

import java.sql.CallableStatement;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

 

import org.apache.commons.lang3.StringUtils;

import org.apache.ibatis.type.BaseTypeHandler;

import org.apache.ibatis.type.JdbcType;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

@Service

public class CustomTypeHandler<T> extends BaseTypeHandler<T> {

 

    @Autowired

    private KeyCenterUtils keyCenterUtils;

 

    public CustomTypeHandler() {

    }

 

    @Override

    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {

        ps.setString(i, this.keyCenterUtils.encrypt((String)parameter));

    }

    @Override

    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {

        String columnValue = rs.getString(columnName);

        //有一些可能是空字符

        return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)this.keyCenterUtils.decrypt(columnValue);

    }

 

    @Override

    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

        String columnValue = rs.getString(columnIndex);

        return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)this.keyCenterUtils.decrypt(columnValue);

    }

 

    @Override

    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {

        String columnValue = cs.getString(columnIndex);

        return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)this.keyCenterUtils.decrypt(columnValue);

    }

}

 

2.3、Handle的使用

2.3.1、数据层实体类注解

package com.healerjean.proj.data.entity;

 

import com.baomidou.mybatisplus.annotation.TableField;

import com.baomidou.mybatisplus.annotation.TableName;

import com.healerjean.proj.config.keycenter.one.CustomTypeHandler;

import lombok.Data;

 

import java.util.Date;

 

@Data

@TableName(autoResultMap = true) //有了这个BaseMapper查询的结果才能解密

public class User {

    private Long id;

    private String name;

    private Integer age;

 

    //有了这个数据库BaseMapper插入的时候才能加密

    @TableField(typeHandler = CustomTypeHandler.class)

    private String telPhone;

 

    @TableField(typeHandler = CustomTypeHandler.class)

    private String email;

 

    private Date createDate;

    private Date createTime;

}

2.3.2、自定义sql查询的配置

如果不是mybatisPlus的 BaseMapper内部的方法,则需要我们自己放入我们自定义的typeHandler

@Results({

    @Result(column = "email", property = "email", typeHandler = CustomTypeHandler.class),

    @Result(column = "tel_phone", property = "telPhone", typeHandler = CustomTypeHandler.class)})

@Select("select * from user where id = #{id}")

List<User> selectDncryptList(Long id);

2.3.3、测试

User中的数据都是正常的 。不是密文。因为我们只讲入库的数据设置了密文。并不会改变User对象本身

 

@Test

public void encrypt(){

    List<User> users = null ;

 

    //插入数据

    User user = new User();

    user.setName("name");

    user.setAge(12);

    user.setEmail("healerjean@gmail.com");

    user.setTelPhone("18841256");

    userMapper.insert(user);

 

 

    //更新

    user.setEmail("12456@gmail.com");

    userMapper.updateById(user);

 

 

    //查询 :列表查询

    users = userMapper.selectList(null);

    System.out.println(users);

 

    //查询 :根据Id查询

    User user1 = userMapper.selectById(user.getId());

    System.out.println(user1);

 

 

    //自定义sql查询

    users  = userMapper.selectDncryptList(user.getId());

    System.out.println(users);

 

 

}

 

 

2.4、敏感字段查询:(需要精确查询)

因为数据库中是密文,所以查询的时候,需要我们先加密后才能查

// 根据敏感字段查询

Wrapper<User> userWrapper = new QueryWrapper<User>().lambda()

    .select(User::getEmail)

    .eq(User::getEmail, keyCenterUtils.encrypt("healerjean@gmail.com"));

 

users  = userMapper.selectList(userWrapper);

System.out.println(users);

 
1、数据库连接加解密1.1、数据库连接配置####################################### DB#####################################duridspring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.druid.driver-class-name=com.mysql.jdbc.Driverspring.datasource.druid.initialSize=5spring.datasource.druid.minIdle=5spring.datasource.druid.maxActive=20spring.datasource.druid.maxWait=60000spring.datasource.druid.timeBetweenEvictionRunsMillis=60000spring.datasource.druid.minEvictableIdleTimeMillis=300000spring.datasource.druid.validationQuery=SELECT 1 FROM DUALspring.datasource.druid.testWhileIdle=truespring.datasource.druid.testOnBorrow=falsespring.datasource.druid.testOnReturn=false


######################################### DB####################################spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/hlj_demo?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=truespring.datasource.druid.username=GCBeAUOZNANpmXfIUPO42qx/dQP80Lae3BI7ABxQN2AzWhgQAG+S6Dhespring.datasource.druid.password=GCAfE1p20be+BX5TZsVlFe1/T1bQ+f2IhnjqOQKe7CJT7xgQ8YOQrf7U####################################


#是否需要数据连接加密spring.datasource.encrypt=true123456789101112131415161718192021222324252627282930311.2、Java数据库连接package com.fintech.confin.web.config;
import com.alibaba.druid.pool.DruidDataSource;import com.fintech.confin.sensitivity.KeycenterUtils;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/** * @author HealerJean * @ClassName DateSourceConfig * @date 2020/4/9  10:43. * @Description */@Configurationpublic class DateSourceConfig {@Value("${spring.datasource.druid.driver-class-name}")private String driverClassName;@Value("${spring.datasource.druid.url}")private String dbUrl;@Value("${spring.datasource.druid.username}")private String username;@Value("${spring.datasource.druid.password}")private String password;@Value("${spring.datasource.druid.initialSize}")private int initialSize;@Value("${spring.datasource.druid.minIdle}")private int minIdle;@Value("${spring.datasource.druid.maxActive}")private int maxActive;@Value("${spring.datasource.druid.maxWait}")private int maxWait;@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")private int timeBetweenEvictionRunsMillis;@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")private int minEvictableIdleTimeMillis;@Value("${spring.datasource.druid.validationQuery}")private String validationQuery;@Value("${spring.datasource.druid.testWhileIdle}")private boolean testWhileIdle;@Value("${spring.datasource.druid.testOnBorrow}")private boolean testOnBorrow;@Value("${spring.datasource.druid.testOnReturn}")private boolean testOnReturn;@Value("${spring.datasource.encrypt}")private boolean encrypt;@Bean(name = "dataSource")public DataSource dataSource(KeycenterUtils keycenterUtils) {DruidDataSource datasource = new DruidDataSource();datasource.setDriverClassName(driverClassName);datasource.setUrl(dbUrl);if (encrypt) {datasource.setUsername(keycenterUtils.decrypt(username));datasource.setPassword(keycenterUtils.decrypt(password));} else {datasource.setUsername(username);datasource.setPassword(password);}datasource.setInitialSize(initialSize);datasource.setMinIdle(minIdle);datasource.setMaxActive(maxActive);datasource.setMaxWait(maxWait);datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);datasource.setValidationQuery(validationQuery);datasource.setTestWhileIdle(testWhileIdle);datasource.setTestOnBorrow(testOnBorrow);datasource.setTestOnReturn(testOnReturn);return datasource;}}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677782、数据库字段加解密2.1、KeyCenterUtils:加解密工具类package com.healerjean.proj.config.keycenter.one;
import org.springframework.stereotype.Service;
import java.util.Base64;
/** * @author HealerJean * @ClassName AES * @date 2020/4/9  14:28. * @Description */@Servicepublic class KeyCenterUtils {
    /**     * 自己写加密逻辑     */    public  String encrypt(String src) {        try {            String result = Base64.getEncoder().encodeToString(src.getBytes("UTF-8"));            return result;        } catch (Exception e) {            throw new RuntimeException("encrypt fail!", e);        }    }
    /**     * 自己写解密逻辑     */    public  String decrypt(String src) {        try {            byte[] asBytes = Base64.getDecoder().decode(src);            String result = new String(asBytes, "UTF-8");            return result;        } catch (Exception e) {            throw new RuntimeException("decrypt fail!", e);        }    }
}
1234567891011121314151617181920212223242526272829303132333435363738394041422.2、CustomTypeHandler数据库字段加解密控制器package com.healerjean.proj.config.keycenter.one;
/** * @author HealerJean * @ClassName AESTypeHandler * @date 2020/4/9  14:27. * @Description */
import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;
import org.apache.commons.lang3.StringUtils;import org.apache.ibatis.type.BaseTypeHandler;import org.apache.ibatis.type.JdbcType;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;
@Servicepublic class CustomTypeHandler<T> extends BaseTypeHandler<T> {
    @Autowired    private KeyCenterUtils keyCenterUtils;
    public CustomTypeHandler() {    }
    @Override    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {        ps.setString(i, this.keyCenterUtils.encrypt((String)parameter));    }    @Override    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {        String columnValue = rs.getString(columnName);        //有一些可能是空字符        return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)this.keyCenterUtils.decrypt(columnValue);    }
    @Override    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {        String columnValue = rs.getString(columnIndex);        return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)this.keyCenterUtils.decrypt(columnValue);    }
    @Override    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {        String columnValue = cs.getString(columnIndex);        return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)this.keyCenterUtils.decrypt(columnValue);    }}

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253542.3、Handle的使用2.3.1、数据层实体类注解package com.healerjean.proj.data.entity;
import com.baomidou.mybatisplus.annotation.TableField;import com.baomidou.mybatisplus.annotation.TableName;import com.healerjean.proj.config.keycenter.one.CustomTypeHandler;import lombok.Data;
import java.util.Date;
@Data@TableName(autoResultMap = true) //有了这个BaseMapper查询的结果才能解密public class User {    private Long id;    private String name;    private Integer age;
    //有了这个数据库BaseMapper插入的时候才能加密    @TableField(typeHandler = CustomTypeHandler.class)    private String telPhone;
    @TableField(typeHandler = CustomTypeHandler.class)    private String email;
    private Date createDate;    private Date createTime;}
1234567891011121314151617181920212223242526272.3.2、自定义sql查询的配置如果不是mybatisPlus的 BaseMapper内部的方法,则需要我们自己放入我们自定义的typeHandler
@Results({    @Result(column = "email", property = "email", typeHandler = CustomTypeHandler.class),    @Result(column = "tel_phone", property = "telPhone", typeHandler = CustomTypeHandler.class)})@Select("select * from user where id = #{id}")List<User> selectDncryptList(Long id);123452.3.3、测试User中的数据都是正常的 。不是密文。因为我们只讲入库的数据设置了密文。并不会改变User对象本身

@Testpublic void encrypt(){    List<User> users = null ;
    //插入数据    User user = new User();    user.setName("name");    user.setAge(12);    user.setEmail("healerjean@gmail.com");    user.setTelPhone("18841256");    userMapper.insert(user);

    //更新    user.setEmail("12456@gmail.com");    userMapper.updateById(user);

    //查询 :列表查询    users = userMapper.selectList(null);    System.out.println(users);
    //查询 :根据Id查询    User user1 = userMapper.selectById(user.getId());    System.out.println(user1);

    //自定义sql查询    users  = userMapper.selectDncryptList(user.getId());    System.out.println(users);

}
12345678910111213141516171819202122232425262728293031323334352.4、敏感字段查询:(需要精确查询)因为数据库中是密文,所以查询的时候,需要我们先加密后才能查
// 根据敏感字段查询Wrapper<User> userWrapper = new QueryWrapper<User>().lambda()    .select(User::getEmail)    .eq(User::getEmail, keyCenterUtils.encrypt("healerjean@gmail.com"));
users  = userMapper.selectList(userWrapper);System.out.println(users);————————————————版权声明:本文为CSDN博主「HealerJean.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/u012954706/article/details/105437768

标签:String,便捷,spring,数据库,加解密,druid,private,datasource,import
From: https://www.cnblogs.com/bulesea/p/17672561.html

相关文章

  • 达梦数据库:第一章:MySQL数据库与达梦数据库的区别
    达梦数据库管理系统是达梦公司推出的具有完全自主知识产权的高性能数据库管理系统,简称DM,它具有如下特点:1、通用性达梦数据库管理系统兼容多种硬件体系,可运行于X86、X64、SPARC、POWER等硬件体系之上。DM各种平台上的数据存储结构和消息通信结构完全一致,使得DM各种组件在不同的硬......
  • 什么是数据库
    数据库是一种用于有效地存储、组织、管理和检索数据的结构化集合或系统。它是计算机科学和信息技术领域中的重要概念,通常用于在计算机系统中持久地存储和管理大量数据。数据库可以容纳各种类型的数据,例如文本、数字、图像、音频和视频等。数据库系统通常包括以下关键组件:数据:......
  • 什么是关系型数据库
    关系型数据库(RelationalDatabase)是一种数据库类型,它以表格(表)的形式组织和存储数据,并使用关系代数来处理数据之间的关系。这种类型的数据库使用了一种称为结构化查询语言(SQL)的标准查询语言来管理和查询数据。关系型数据库的主要特点包括:表格结构:数据以表格的形式组织,每个表格......
  • winform,c#左链接查询两张表或多张表,数据库正常,但是发现查出来的同一条记录变成了好几
    这个样子就是犯了笛卡尔积,我有两张表那我自己项目来说一下吧:a表的内容如下: b表的内容如下: 到这里,你会发现,又五六个字段内容是一模一样的,该字段两张表都用,那么查询出来数据翻倍就很好解决了在where后面加上a.字段1=b.字段1and......anda.字段n=b.字段n就可以了......
  • 8月《中国数据库行业分析报告》已发布,聚焦数据仓库、首发【全球数据仓库产业图谱】
    为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况,从2022年4月起,墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》,持续传播数据技术知识、努力促进技术创新与行业生态发展,目前已更至第十六期,并发布了共计1......
  • dbeaver连接国产数据库highgo
    一、下载jar包HgdbJdbc,找项目中的jar包即可。 二、配置模板驱动名:Highgo类名:com.highgo.jdbc.DriverURL模板:jdbc:highgo://{host}:{port}/{database}端口:5866默认数据库:highgo ......
  • mysql数据库运行sql:datetime(0) NULL DEFAULT NULL报错【杭州多测师_王sir】
     一、错误信息CREATETABLE`file`(`id`varchar(32)CHARACTERSETutf8mb4COLLATEutf8mb4_general_ciNOTNULLCOMMENT'文件md5',`name`varchar(128)CHARACTERSETutf8mb4COLLATEutf8mb4_general_ciNOTNULL,`create_time`datetime(0)NULLDEFA......
  • 干货分享,现代列式数据库系统如何设计与实现? | StoneData 论文选读
    作者:袁洋 |StoneData技术架构师审核:王博论文链接:columnstoresfntdbs.pdf(harvard.edu)列存四先驱和MIT知名教授SamuelMadden于2013年在某期刊上写的一篇当时列存相关技术的综述。文章还挺全面也很经典,通过剖析三个经典的现代列存的数据库C-store、MonetDB、VectorWise,......
  • 阿里云亮相数据库顶会 VLDB 2023 特邀主旨演讲:云数据库要像乐高积木一样好用
    北京时间8月30日,数据库国际顶会VLDB在加拿大温哥华开幕,来自阿里云、达摩院及合作者的论文共入选17篇,其中工业赛道(Industrial Track)收录7篇阿里云论文,均刷新中国企业纪录。在VLDB大会现场,阿里云数据库负责人李飞飞作大会特邀主旨演讲时表示,随着云计算基础设施的完善和......
  • SQL Server 操作JSON数据库列
    use[tempdb]declare@JSONnvarchar(max)set@JSON=N'{"id":"WakefieldFamily","parents":[{"familyName":"Wakefield","givenName":"Robin"},{"familyNam......