数据加密(数据加密方式有哪些)

  本篇文章为你整理了数据加密(数据加密方式有哪些)的详细内容,包含有数据加密技术 数据加密方式有哪些 数据加密传输 数据加密存储 数据加密,希望能帮助你了解 数据加密。

  数据库存储密文字段,内存可见为明文信息

  可设定字段保存值支持 整体加密(仅可全部匹配查询)、模糊加密(支持模糊查询)

  相关做法: 数据库隐私字段加密以及加密后的数据如何进行模糊查询? - 业余草

  
实现做法:常规二,对明文数据进行分词组合,将分词组合的结果集分别进行加密存储,查询时通过 column LIKE %partial%
 

  分组规则:按固定长度,根据4位英文字符(半角),2个中文字符(全角)为一个检索条件
 

  分组示例:ningyu1 使用4个字符为一组的加密方式 - ning + ingy + ngyu + gyu1

  
varchar(97)

  24个中文字符、72个ascii字符、3个ascii字符+23个中文字符、68个ascii字符+1个中文字符

  
varchar(197)

  49个中文字符、145个ascii字符、3个ascii字符+48个中文字符 、 142个ascii字符+1个中文字符

  
varchar(253)

  63个中文字符、189个ascii字符 、3个ascii字符+62个中文字符 、 186个ascii字符+1个中文字符

  
模糊加密数据库字段长度与保存值长度对应(4个字节加密一次大致对应8个字符+1个标识符),根据4位英文字符(半角),2个中文字符(全角)为一个检索条件

  
INSERT VALUE、UPDATE ENTITY、SELECT RESULT
 

  只对数据库和程序之间的数据转换,查询条件不会调用。

  
1. MyBatis-Plus 注解(自动生产 ResultMap ,存在场景不生效)

   @TableField(typeHandler = OverallCryptoTypeHandler.class)

  2. 自定义 ResultMap 配置

   result column="phone" property="phone" typeHandler="cn.eastx.practice.demo.crypto.config.mp.OverallCryptoTypeHandler" /

  

 

 

   整体加密类型处理器 OverallCryptoTypeHandler.java

  

@Override

 

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

   对非null参数值进行加密,需要通过实体类处理方可,支持 INSERT/UPDATE ENTITY

   当前处理 INSERT ENTITY,UPDATE ENTITY 会先通过拦截器处理

   因为拦截器修改元数据将导致实体类属性值产生变更,所以实体类还是由 TypeHandler 来进行处理

   ps.setString(i, CryptoDataUtil.overallEncrypt(parameter));

  @Override

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

   // 对可为null的结果进行解密

   return CryptoDataUtil.decrypt(rs.getString(columnName));

  

 

  
模糊加密类型处理器
 

  注意:根据4位英文字符(半角),2个中文字符(全角)为一个检索条件,如果字段值较少查询可能存在问题

  

 使用示例:

 

   1. MyBatis-Plus 注解(自动生产 ResultMap ,存在场景不生效)

   @TableField(typeHandler = FuzzyCryptoTypeHandler.class)

   2. 自定义 ResultMap 配置

   result column="phone" property="phone" typeHandler="cn.eastx.practice.demo.crypto.config.mp.FuzzyCryptoTypeHandler" /

  

 

   模糊加密类型处理器 FuzzyCryptoTypeHandler.java

  

@Override

 

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

   对非null参数值进行加密,需要通过实体类处理方可,支持 INSERT/UPDATE ENTITY

   当前处理 INSERT ENTITY,UPDATE ENTITY 会先通过拦截器处理

   因为拦截器修改元数据将导致实体类属性值产生变更,所以实体类还是由 TypeHandler 来进行处理

   ps.setString(i, CryptoDataUtil.fuzzyEncrypt(parameter));

  @Override

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

   // 对可为null的结果进行解密

   return CryptoDataUtil.decrypt(rs.getString(columnName));

  

 

  
使用 replacedColumn() 替换 SQL 查询条件中的字段名

  使用 encryption() 对 SQL 中条件值、参数值进行加密,支持两种方式(整体匹配、模糊匹配)

  使用示例:User.java

  
实现 Interceptor 接口,重写拦截器拦截 SQL 逻辑

  拦截器执行在 TypeHandler 之前,注意避免冲突

  
public Object intercept(Invocation invocation) throws Throwable {

   StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());

   MetaObject metaObject = SystemMetaObject.forObject(statementHandler);

   MappedStatement mappedStatement =

   (MappedStatement) metaObject.getValue("delegate.mappedStatement");

   // 支持处理 SELECT、UPDATE、DELETE

   boolean canHandler = Stream.of(SqlCommandType.SELECT, SqlCommandType.UPDATE,

   SqlCommandType.DELETE)

   .anyMatch(item - item.equals(mappedStatement.getSqlCommandType()));

   if (canHandler !getIntercept()) {

   clearIntercept();

   return invocation.proceed();

   clearIntercept();

   // 判断是否有参数需要处理

   BoundSql boundSql = statementHandler.getBoundSql();

   if (Objects.isNull(boundSql.getParameterObject())) {

   return invocation.proceed();

   // 获取自定义注解,通过 MapperID 获取到 Mapper 对应的实体类,获取实体类所有注解字段与注解对应 Map

   Map String, CryptoCond condMap = mapEntityFieldCond(mappedStatement.getId());

   if (CollectionUtil.isNotEmpty(condMap)) {

   replaceHandle(mappedStatement.getConfiguration(), condMap, boundSql);

   return invocation.proceed();

  // 替换数据处理

  private void replaceHandle(Configuration configuration, Map String, CryptoCond condMap,

   BoundSql boundSql) {

   String sql = boundSql.getSql();

   Pair String, List SqlCondOperation sqlPair = SqlUtil.getSqlCondOperationPair(sql);

   List SqlCondOperation operationList = sqlPair.getValue();

   if (CollectionUtil.isEmpty(operationList)) {

   return;

   sql = sqlPair.getKey();

   MetaObject paramMetaObject = configuration.newMetaObject(boundSql.getParameterObject());

   List ParameterMapping mappings = boundSql.getParameterMappings();

   int mappingStartIdx = 0;

   int addIdxLen = 0;

   for (SqlCondOperation operation : operationList) {

   String condStr = operation.getOriginCond();

   int prepareNum = SqlUtil.countPreparePlaceholder(condStr);

   CryptoCond ann = condMap.get(operation.getColumnName());

   if (Objects.nonNull(ann)) {

   // 替换查询条件参数中的列名

   if (StrUtil.isNotBlank(ann.replacedColumn()) !operation.checkSetCond()) {

   sql = operation.replaceSqlCond(sql, addIdxLen,

   operation.getColumnName(), ann.replacedColumn());

   // 替换属性值为加密值

   if (prepareNum == 0) {

   // 存在非预编译语句条件,直接替换 SQL 条件值

   String propVal =

   String.valueOf(paramMetaObject.getValue(operation.getColumnName()));

   String useVal = getCryptoUseVal(ann, propVal);

   sql = operation.replaceSqlCond(sql, addIdxLen, propVal, useVal);

   } else {

   // 预编译语句条件通过替换条件值处理

   for (int i = 0; i prepareNum; i++) {

   String propName = mappings.get(mappingStartIdx + i).getProperty();

   if (!propName.startsWith("et.")) {

   // 非实体类属性进行值替换,实体类属性通过 TypeHandler 处理

   String propVal = String.valueOf(paramMetaObject.getValue(propName));

   paramMetaObject.setValue(propName, getCryptoUseVal(ann, propVal));

   mappingStartIdx += prepareNum;

   addIdxLen += operation.getOriginCond().length() - condStr.length();

   ReflectUtil.setFieldValue(boundSql, "sql", sql);

  

 

 

  
执行 /resources/db/schema.sql 创建数据库( java-practice-demos )、示例表( crypto-user )

  用户表 Service 层 IUserService.java

  用户表 Service 层 测试 UserServiceTest.java
 

  使用问题

  
点击查看代码 UserMapper.xml

  

 !-- 使用自定义SQL时,对于加密处理需要使用ResultMap作为返回对象,否则对解析成实际数据会存在问题 -- 

 

   resultMap id="BaseResultMap" type="cn.eastx.practice.demo.crypto.pojo.po.User"

   result column="id" property="id" /

   result column="name" property="name" /

   result column="password" property="password" /

   result column="salt" property="salt" /

   result column="phone" property="phone" typeHandler="cn.eastx.practice.demo.crypto.config.mp.OverallCryptoTypeHandler" /

   result column="email" property="email" typeHandler="cn.eastx.practice.demo.crypto.config.mp.FuzzyCryptoTypeHandler" /

   result column="create_time" property="createTime" /

   result column="update_time" property="updateTime" /

   /resultMap

  

 

  
设置 CryptoCondInterceptor.setIntercept(false)

  在实体类上相应字段设置 @CryptoCond ,示例:User.java

  
@TableField(typeHandler = OverallCryptoTypeHandler.class)

   @CryptoCond(encryption = CryptoCond.EncryptionEnum.DEFAULT_OVERALL)

   private String phone;

   * 邮箱,模糊加密

   @TableField(typeHandler = FuzzyCryptoTypeHandler.class)

   @CryptoCond(encryption = CryptoCond.EncryptionEnum.DEFAULT_FUZZY)

   private String email;

   * 创建时间

   @TableField(fill = INSERT)

   private LocalDateTime createTime;

   * 更新时间

   @TableField(fill = INSERT_UPDATE)

   private LocalDateTime updateTime;

  

 

 

  
Mapper 实现 BaseMapper 并指定实体类,示例:public interface UserMapper extends BaseMapper User

  将拦截器加入 Spring IOC 管理

  以上就是数据加密(数据加密方式有哪些)的详细内容,想要了解更多 数据加密的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: