当前位置: 首页 > news >正文

徐州建设银行网上银行个人网站服装品牌策划及营销推广方案

徐州建设银行网上银行个人网站,服装品牌策划及营销推广方案,wordpress商城系统,做U启的网站目录1.场景介绍2.Maven依赖2.AESUtil.java 加解密工具类3.字段处理类4.修改 MyBatis Plus 查询4.1 修改表对应实体类4.2 修改加密字段对应属性4.3 修改 xml 使用 ResultMap4.4 修改 xml 中 el 表达式5.测试结果6.MyBatis Plus 缺陷补充:测试实例1 查询测试1.1 查询信…

目录

    • 1.场景介绍
    • 2.Maven依赖
    • 2.AESUtil.java 加解密工具类
    • 3.字段处理类
    • 4.修改 MyBatis Plus 查询
      • 4.1 修改表对应实体类
      • 4.2 修改加密字段对应属性
      • 4.3 修改 xml 使用 ResultMap
      • 4.4 修改 xml 中 el 表达式
    • 5.测试结果
    • 6.MyBatis Plus 缺陷
    • 补充:测试实例
      • 1 查询测试
        • 1.1 查询信息,SQL实现
        • 1.2 查询信息,QueryWrapper实现
        • 1.3 查询信息,根据加密字段查询,SQL实现
        • 1.4 查询信息,根据加密字段查询,QueryWrapper实现
      • 2.测试更新
        • 2.1 更新信息,SQL实现
        • 2.2 更新信息,UpdateWrapper实现
        • 2.3 更新信息,LambdaUpdateWrapper实现
        • 2.4 更新信息,updateById实现
      • 3.测试插入
        • 7.3.1 插入信息,SQL实现
        • 3.2 插入信息,Service实现

1.场景介绍

  • 当项目开发到一半,可能突然客户会要求对数据库里面比如手机号、身份证号的字段进行加密;
  • 在保证开发最快、影响范围最小的情况下,我们需要选择一种介于数据库和代码之间的工具来帮我们实现自动加解密;

2.Maven依赖

<!-- mybatis-plus -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3</version>
</dependency><!-- mybatis的分页插件 -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.11</version><!-- pagehelper 包含该依赖存在版本冲突,因此不建议和 mp 一起混用 --><exclusions><exclusion><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId></exclusion></exclusions>
</dependency>

2.AESUtil.java 加解密工具类

这里我们选用AES对称加密算法,因为它是可逆算法。

AES加密介绍: https://blog.csdn.net/qq_33204709/article/details/126930720

具体实现代码如下:

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;/*** AES加密工具类** @author ACGkaka* @since 2021-06-18 19:11:03*/
public class AESUtil {/*** 日志相关*/private static final Logger LOGGER = LoggerFactory.getLogger(AESUtil.class);/*** 编码*/private static final String ENCODING = "UTF-8";/*** 算法定义*/private static final String AES_ALGORITHM = "AES";/*** 指定填充方式*/private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding";private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS5Padding";/*** 偏移量(CBC中使用,增强加密算法强度)*/private static final String IV_SEED = "1234567812345678";/*** AES加密* @param content 待加密内容* @param aesKey  密码* @return*/public static String encrypt(String content, String aesKey){if(StringUtils.isBlank(content)){LOGGER.info("AES encrypt: the content is null!");return null;}//判断秘钥是否为16位if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置加密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_PADDING);//选择加密cipher.init(Cipher.ENCRYPT_MODE, skeySpec);//根据待加密内容生成字节数组byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));//返回base64字符串return Base64Utils.encodeToString(encrypted);} catch (Exception e) {LOGGER.info("AES encrypt exception:" + e.getMessage());throw new RuntimeException(e);}}else {LOGGER.info("AES encrypt: the aesKey is null or error!");return null;}}/*** 解密* * @param content 待解密内容* @param aesKey  密码* @return*/public static String decrypt(String content, String aesKey){if(StringUtils.isBlank(content)){LOGGER.info("AES decrypt: the content is null!");return null;}//判断秘钥是否为16位if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置解密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_PADDING);//选择解密cipher.init(Cipher.DECRYPT_MODE, skeySpec);//先进行Base64解码byte[] decodeBase64 = Base64Utils.decodeFromString(content);//根据待解密内容进行解密byte[] decrypted = cipher.doFinal(decodeBase64);//将字节数组转成字符串return new String(decrypted, ENCODING);} catch (Exception e) {LOGGER.info("AES decrypt exception:" + e.getMessage());throw new RuntimeException(e);}}else {LOGGER.info("AES decrypt: the aesKey is null or error!");return null;}}/*** AES_CBC加密* * @param content 待加密内容* @param aesKey  密码* @return*/public static String encryptCBC(String content, String aesKey){if(StringUtils.isBlank(content)){LOGGER.info("AES_CBC encrypt: the content is null!");return null;}//判断秘钥是否为16位if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置加密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);//偏移IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));//选择加密cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);//根据待加密内容生成字节数组byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));//返回base64字符串return Base64Utils.encodeToString(encrypted);} catch (Exception e) {LOGGER.info("AES_CBC encrypt exception:" + e.getMessage());throw new RuntimeException(e);}}else {LOGGER.info("AES_CBC encrypt: the aesKey is null or error!");return null;}}/*** AES_CBC解密* * @param content 待解密内容* @param aesKey  密码* @return*/public static String decryptCBC(String content, String aesKey){if(StringUtils.isBlank(content)){LOGGER.info("AES_CBC decrypt: the content is null!");return null;}//判断秘钥是否为16位if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置解密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);//偏移IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);//选择解密cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);//先进行Base64解码byte[] decodeBase64 = Base64Utils.decodeFromString(content);//根据待解密内容进行解密byte[] decrypted = cipher.doFinal(decodeBase64);//将字节数组转成字符串return new String(decrypted, ENCODING);} catch (Exception e) {LOGGER.info("AES_CBC decrypt exception:" + e.getMessage());throw new RuntimeException(e);}}else {LOGGER.info("AES_CBC decrypt: the aesKey is null or error!");return null;}}public static void main(String[] args) {// AES支持三种长度的密钥:128位、192位、256位。// 代码中这种就是128位的加密密钥,16字节 * 8位/字节 = 128位。String random = RandomStringUtils.random(16, "abcdefghijklmnopqrstuvwxyz1234567890");System.out.println("随机key:" + random);System.out.println();System.out.println("---------加密---------");String aesResult = encrypt("测试AES加密12", random);System.out.println("aes加密结果:" + aesResult);System.out.println();System.out.println("---------解密---------");String decrypt = decrypt(aesResult, random);System.out.println("aes解密结果:" + decrypt);System.out.println();System.out.println("--------AES_CBC加密解密---------");String cbcResult = encryptCBC("测试AES加密12456", random);System.out.println("aes_cbc加密结果:" + cbcResult);System.out.println();System.out.println("---------解密CBC---------");String cbcDecrypt = decryptCBC(cbcResult, random);System.out.println("aes解密结果:" + cbcDecrypt);System.out.println();}
}

3.字段处理类

import com.demo.util.AESUtil;
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;/*** <p> @Title MyEncryptTypeHandler* <p> @Description 字段加密处理** @author ACGkaka* @date 2023/2/21 17:20*/
public class MyEncryptTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, AESUtil.defaultEncrypt(parameter));}@Overridepublic String getNullableResult(ResultSet rs, String column) throws SQLException {return AESUtil.defaultDecrypt(rs.getString(column));}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return AESUtil.defaultDecrypt(rs.getString(columnIndex));}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return AESUtil.defaultDecrypt(cs.getString(columnIndex));}
}

4.修改 MyBatis Plus 查询

4.1 修改表对应实体类

设置 @TableName 注解的 autoResultMap 为 true,默认 false。

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;/*** 用户表** @author ACGkaka* @date 2023/2/21 17:20*/
@Data
@TableName(value = "t_user_info", autoResultMap = true)
public class UserInfo implements Serializable {}

4.2 修改加密字段对应属性

设置 @TableField 注解的 typeHandlerMyEncryptTypeHandler.class

import com.demo.encrypt.MyEncryptTypeHandler;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;/*** 用户表** @author ACGkaka* @date 2023/2/21 17:20*/
@Data
@TableName(value = "t_user_info", autoResultMap = true)
public class UserInfo implements Serializable {/*** 手机号码*/@TableField(value = "PHONE", typeHandler = MyEncryptTypeHandler.class)private String phone;
}

4.3 修改 xml 使用 ResultMap

1)创建 ResultMap 映射,指定 typeHandler

2)查询语句使用 ResultMap 返回。

<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.demo.model.UserInfo"><id column="ID" property="id" /><result column="ACCOUNT" property="staffCode" /><result column="PHONE" property="phone" typeHandler="com.demo.encrypt.MyEncryptTypeHandler" />
</resultMap><!-- 查询全部 -->
<select id="findAll" resultMap="BaseResultMap">SELECT * FROM t_user_info
</select>

4.4 修改 xml 中 el 表达式

设置好 4.1 和 4.2 就可以保证

修改前:

<!-- 更新手机号 -->
<update id="updatePhoneById">update t_user_info set phone = #{phone} where id = #{id}
</update><!-- 根据手机号查询 -->
<select id="findByPhone" resultMap="BaseResultMap">SELECT * FROM t_user_info where phone = #{phone}
</select>

修改后:

<!-- 更新手机号 -->
<update id="updatePhoneById">update t_user_info set phone = #{phone, typeHandler=com.demo.encrypt.MyEncryptTypeHandler} where id = #{id}
</update><!-- 根据手机号查询 -->
<select id="findByPhone" resultMap="BaseResultMap">SELECT * FROM t_user_info where phone = #{phone, typeHandler=com.demo.encrypt.MyEncryptTypeHandler}
</select>

5.测试结果

由于测试内容较多,这里先直接展示测试结果,具体测试示例可以看 补充:测试实例

操作实现方式入参测试结果
SELECT原生SQL非加密字段出参解密成功
SELECTQueryWrapper非加密字段出参解密成功
SELECT原生SQL加密字段入参加密成功
SELECTQueryWrapper加密字段入参加密失败
UPDATE原生SQL加密字段入参加密成功
UPDATEUpdateWrapper加密字段入参加密失败
UPDATELambdaUpdateWrapper加密字段入参加密成功
UPDATEupdateById加密字段入参加密成功
INSERTService加密字段入参加密成功

说明:

  • 官方的解答是 QueryWrapper、UpdateWrapper 底层是通过 @Param 来实现的,目前没有做到入参支持 typeHandler,如果做的话会影响性能。

6.MyBatis Plus 缺陷

  • QueryWrapper 不支持入参加密;

  • UpdateWrapper 不支持入参加密;

  • 加密字段不支持模糊查询。

补充:测试实例

1 查询测试

1.1 查询信息,SQL实现

@Test
public void getUserInfoTest1() {UserInfo userInfo = userInfoService.findByAccount("testAccount");System.out.println("userInfo:" + userInfo);System.out.println("phone:" + userInfo.getPhone());
}

测试结果:出参解密成功

1.2 查询信息,QueryWrapper实现

@Test
public void getUserInfoTest2() {QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();wrapper.eq("account", "testAccount");List<UserInfo> users = userInfoService.list(wrapper);System.out.println("userInfo:" + users);System.out.println("phone:" + users.get(0).getPhone());
}

测试结果:出参解密成功

1.3 查询信息,根据加密字段查询,SQL实现

@Test
public void getUserInfoTest3() {UserInfo user = userInfoService.findByPhone("13888888888");System.out.println("userInfo:" + user);System.out.println("phone:" + user.getPhone());
}

(注意:入参需要使用el表达式指定 typeHandler)

测试结果:入参加密成功

1.4 查询信息,根据加密字段查询,QueryWrapper实现

@Test
public void getUserInfoTest3() {QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();wrapper.lambda().eq(UserInfo::getPhone, "13888888888");List<UserInfo> users = userInfoService.list(wrapper);System.out.println("userInfo:" + users);System.out.println("phone:" + users.get(0).getPhone());
}

测试结果:入参加密失败,QueryWrapper底层使用 @Param 实现,无法像 SQL 实现一样指定 typeHandler。

2.测试更新

2.1 更新信息,SQL实现

@Test
public void updateUserInfoTest1() {userInfoService.updatePhoneByAccount("testAccount", "13888888888");
}

测试结果:入参加密成功

2.2 更新信息,UpdateWrapper实现

@Test
public void updateUserInfoTest2() {UpdateWrapper<UserInfo> wrapper = new UpdateWrapper<>();wrapper.set("phone", "13888888888");wrapper.eq("account", "testAccount");userInfoService.update(wrapper);getUserInfoTest1();
}

测试结果:入参加密失败,UpdateWrapper底层使用 @Param 实现,无法像 SQL 实现一样指定 typeHandler。

2.3 更新信息,LambdaUpdateWrapper实现

@Test
public void updateUserInfoTest3() {LambdaUpdateWrapper<UserInfo> wrapper = Wrappers.<UserInfo>lambdaUpdate().set(UserInfo::getPhone, "13888888888", "typeHandler=com.demo.encrypt.MyEncryptTypeHandler");wrapper.eq(UserInfo::getAccount, "testAccount");userInfoService.update(wrapper);getUserInfoTest1();
}

测试结果:入参加密成功

2.4 更新信息,updateById实现

@Test
public void updateUserInfoTest4() {UserInfo userInfo = userInfoService.findByAccount("testAccount");userInfo.setPhone("13888888888");userInfoService.updateById(userInfo);
}

测试结果:入参加密成功

3.测试插入

7.3.1 插入信息,SQL实现

@Test
public void insertUserInfoTest1() {UserInfo userInfo = userInfoService.findByAccount("testAccount");userInfo.setAccount("testAccount_002");userInfo.setPhone("13888888888");userInfoService.save(userInfo);UserInfo newUserInfo = userInfoService.findByAccount("testAccount_002");System.out.println("userInfo:" + newUserInfo);System.out.println("phone:" + newUserInfo.getPhone());
}

测试结果:入参加密成功

3.2 插入信息,Service实现

@Test
public void insertUserInfoTest1() {UserInfo userInfo = userInfoService.findByAccount("testAccount");userInfo.setAccount("testAccount_002");userInfo.setPhone("13888888888");userInfoService.save(userInfo);UserInfo newUserInfo = userInfoService.findByAccount("testAccount_002");System.out.println("userInfo:" + newUserInfo);System.out.println("phone:" + newUserInfo.getPhone());
}

测试结果:入参加密成功

整理完毕,完结撒花~





参考地址:

1.mybaits plus 字段加密与解密,https://blog.csdn.net/qq_21134059/article/details/121752978

2.mybatis plus 官方问题页面,https://github.com/baomidou/mybatis-plus/issues

3.更新时自定义的TypeHandler不生效,https://github.com/baomidou/mybatis-plus/issues/794

4.lambdaUpdate() 无法更新Json对象字段,https://github.com/baomidou/mybatis-plus/issues/5031

5.LambdaUpdateWrapper不支持自定义BaseTypeHandler,https://github.com/baomidou/mybatis-plus/issues/3317

http://www.hrbkazy.com/news/53320.html

相关文章:

  • 免费做网站教程网络营销软件站
  • 山东建设厅执业资格注册中心网站最有效的宣传方式
  • 济南住房与城乡建设官网超级优化大师下载
  • wordpress 翻页没内容seo优化顾问
  • 南宁有做门户网站的公司吗链友之家
  • axure中继器做网站qq引流推广平台
  • 建设银行关闭网站查询信用卡账单搜索引擎关键词seo优化公司
  • 源码做微信电影网站幽默广告软文案例
  • win7做系统网站哪个好谷歌海外广告投放
  • 深圳网站建设在哪里找市场调研方法
  • 服装网站建设的规模和类别网站降权查询工具
  • 广州天拓做网站吗国内新闻最新消息10条
  • 网站建设难么产品推广广告
  • 温州网站建设怎么样aso优化排名
  • 手机网站怎么放到桌面上搜索引擎关键词怎么优化
  • 寻找企业网站建设网络营销图片素材
  • 外卖网站的建设与推广网络营销服务企业
  • 专门做nba评论的网站百度官方app免费下载
  • 怎么做自己网站大数据网站
  • 网站搜索引擎优化方案站长工具seo源码
  • 做特殊任务的网站官网建站多少钱
  • b2b网站产品群发工具网推app怎么推广
  • 网加商学院网站怎么做如何去除痘痘有效果
  • 网站建设可用性的五个标准抖音代运营大概多少钱一个月
  • 网站建设文化传播有限公司推广seo公司
  • 丽水做网站的公司抖音搜索优化
  • 专业的做网站的中央新闻频道直播今天
  • 网站开发流程相关知识长春seo按天计费
  • 丰浩网站建设中心搜索引擎优化与关键词的关系
  • 商标logo在线生成优化设计答案六年级上册