springboot實(shí)現(xiàn)敏感字段加密存儲解密顯示功能
springboot實(shí)現(xiàn)敏感字段加密存儲,解密顯示,通過mybatis,自定義注解+AOP切面,Base64加解密方式實(shí)現(xiàn)功能。
1.代碼實(shí)現(xiàn):
創(chuàng)建springboot項目
添加依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <!--mysql數(shù)據(jù)庫驅(qū)動--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <!--mybatis--> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.6</version>
yml配置
server: port: 8081 spring: #數(shù)據(jù)庫連接配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&useSSL=false username: root password: 123456 #mybatis的相關(guān)配置 mybatis: #mapper配置文件 mapper-locations: classpath:mapper/*.xml type-aliases-package: com.cxh.mybatis.entity #開啟駝峰命名 configuration: map-underscore-to-camel-case: true
自定義注解
//表示要加密的字段 @Target({ElementType.FIELD,ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface EncryptField { String[] value() default ""; }
//表示需解密 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface NeedDecrypt { }
//表示需加密 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface NeedEncrypt { }
AOP切面
import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.lang.reflect.Field; import java.util.Objects; //加密AOP @Slf4j @Aspect @Component public class EncryptAspect { //攔截需加密注解 @Pointcut("@annotation(com.cxh.mybatis.test.NeedEncrypt)") public void pointCut() { } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { //加密 encrypt(joinPoint); return joinPoint.proceed(); public void encrypt(ProceedingJoinPoint joinPoint) { Object[] objects=null; try { objects = joinPoint.getArgs(); if (objects.length != 0) { for (int i = 0; i < objects.length; i++) { //拋磚引玉 ,可自行擴(kuò)展其他類型字段的判斷 if (objects[i] instanceof String) { objects[i] = encryptValue(objects[i]); } else { encryptObject(objects[i]); } } } } catch (Exception e) { e.printStackTrace(); } /** * 加密對象 * @param obj * @throws IllegalAccessException */ private void encryptObject(Object obj) throws IllegalAccessException { if (Objects.isNull(obj)) { log.info("當(dāng)前需要加密的object為null"); return; Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { boolean containEncryptField = field.isAnnotationPresent(EncryptField.class); if (containEncryptField) { //獲取訪問權(quán) field.setAccessible(true); if(field.get(obj) != null){ String value = Base64Util.getBase64(String.valueOf(field.get(obj))); field.set(obj, value); * 加密單個值 * @param realValue * @return public String encryptValue(Object realValue) { realValue = Base64Util.getBase64(String.valueOf(realValue)); log.info("加密異常={}",e.getMessage()); return String.valueOf(realValue); }
import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Objects; //解密AOP @Slf4j @Aspect @Component public class DecryptAspect { //攔截需解密注解 @Pointcut("@annotation(com.cxh.mybatis.test.NeedDecrypt)") public void pointCut() { } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { //解密 Object result = decrypt(joinPoint); return result; public Object decrypt(ProceedingJoinPoint joinPoint) { Object result = null; try { Object obj = joinPoint.proceed(); if (obj != null) { //拋磚引玉 ,可自行擴(kuò)展其他類型字段的判斷 if (obj instanceof String) { decryptValue(obj); } else { result = decryptData(obj); } } } catch (Throwable e) { e.printStackTrace(); } private Object decryptData(Object obj) throws IllegalAccessException { if (Objects.isNull(obj)) { return null; if (obj instanceof ArrayList) { decryptList(obj); } else { decryptObj(obj); return obj; /** * 針對單個實(shí)體類進(jìn)行 解密 * @param obj * @throws IllegalAccessException */ private void decryptObj(Object obj) throws IllegalAccessException { Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { boolean hasSecureField = field.isAnnotationPresent(EncryptField.class); if (hasSecureField) { field.setAccessible(true); if(field.get(obj) != null) { String realValue = (String) field.get(obj); String value = Base64Util.getFromBase64(realValue); field.set(obj, value); * 針對list<實(shí)體來> 進(jìn)行反射、解密 private void decryptList(Object obj) throws IllegalAccessException { List<Object> result = new ArrayList<>(); for (Object o : (List<?>) obj) { result.add(o); for (Object object : result) { decryptObj(object); public String decryptValue(Object realValue) { realValue = Base64Util.getFromBase64(String.valueOf(realValue)); } catch (Exception e) { log.info("解密異常={}", e.getMessage()); return String.valueOf(realValue); }
BASE64加解密工具類
import java.io.UnsupportedEncodingException; import org.springframework.stereotype.Component; import sun.misc.*; public class Base64Util { // 加密 public static String getBase64(String str) { byte[] b = null; String s = null; try { b = str.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } if (b != null) { s = new BASE64Encoder().encode(b); return s; } // 解密 public static String getFromBase64(String s) { String result = null; if (s != null) { BASE64Decoder decoder = new BASE64Decoder(); try { b = decoder.decodeBuffer(s); result = new String(b, "utf-8"); } catch (Exception e) { e.printStackTrace(); } return result; public static void main(String[] args) { String a = "123456"; String b = getBase64(a); System.out.println(b); System.out.println(getBase64(a)); System.out.println(getFromBase64(b)); }
控制層
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/findAll") public List<User> findAll(){ return userService.findAll(); } @RequestMapping("/add") @NeedEncrypt public int add(User user){ return userService.add(user); @RequestMapping("/get") @NeedDecrypt public List<User> get(User user){ return userService.get(user); @RequestMapping("/getByName") public List<User> getByName(String username){ User user = new User(); user.setUsername(Base64Util.getBase64(username)); }
service實(shí)現(xiàn)類
@Service("userService") public class UserServiceimpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> findAll() { return userMapper.findAll(); } public Integer add(User user) { return userMapper.add(user); public List<User> get(User user) { return userMapper.get(user); }
userMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.cxh.mybatis.mapper.UserMapper"> <select id="findAll" resultType="User"> SELECT * FROM tb_user </select> <insert id="add" parameterType="User"> INSERT INTO tb_user(`id`, `username`, `password`) VALUES (#{id}, #{username}, #{password}); </insert> <select id="get" resultType="User" parameterType="User"> <where> <if test="id != null and id != ''"> and id = #{id} </if> <if test="username != null and username != ''"> and username = #{username} <if test="password != null and password != ''"> and password = #{password} </where> </mapper>
2.實(shí)現(xiàn)效果:
運(yùn)行項目,打開postman,發(fā)起插入請求:localhost:8081/user/add
查看數(shù)據(jù)庫,顯示數(shù)據(jù)已加密
發(fā)起查詢請求localhost:8081/user/get,顯示數(shù)據(jù)已解密
發(fā)起查詢所有請求localhost:8081/user/findAll,由于該方法沒有添加解密注解,所以數(shù)據(jù)還是加密的。
到此這篇關(guān)于springboot實(shí)現(xiàn)敏感字段加密存儲,解密顯示的文章就介紹到這了,更多相關(guān)springboot敏感字段加密存儲解密顯示內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot使用AES對JSON數(shù)據(jù)加密和解密的實(shí)現(xiàn)方法
- springboot使用國產(chǎn)加密算法方式,sm2和sm3加解密demo
- Springboot接口返回參數(shù)及入?yún)SA加密解密的過程詳解
- SpringBoot實(shí)現(xiàn)接口參數(shù)加密解密的示例代碼
- 關(guān)于Springboot數(shù)據(jù)庫配置文件明文密碼加密解密的問題
- springboot實(shí)現(xiàn)注冊加密與登錄解密功能(demo)
- SpringBoot接口加密解密統(tǒng)一處理
- 在SpringBoot中通過jasypt進(jìn)行加密解密的方法
- Springboot實(shí)現(xiàn)密碼的加密解密
- SpringBoot實(shí)現(xiàn)國密SM4加密解密的使用示例

SpringMVC中的DispatcherServlet初始化流程詳解

Java中Stream流中map和forEach的區(qū)別詳解

spring boot項目fat jar瘦身的實(shí)現(xiàn)