最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot AOP對指定敏感字段數(shù)據(jù)加密存儲的實現(xiàn)

 更新時間:2021年11月19日 11:55:53   作者:小目標青年  
本篇文章主要介紹了利用Springboot+AOP對指定的敏感數(shù)據(jù)進行加密存儲以及對數(shù)據(jù)中加密的數(shù)據(jù)的解密的方法,代碼詳細,具有一定的價值,感興趣的小伙伴可以了解一下

前言

本文主要內(nèi)容:

1. 插入數(shù)據(jù) 自定義注解方式  對 指定接口方法 的 參數(shù)的指定字段進行 加密存儲;

2.對數(shù)據(jù)內(nèi)的加密數(shù)據(jù),進行解密返回

先看看效果 :

數(shù)據(jù)存入數(shù)據(jù)庫表內(nèi), 手機號phone和郵箱email 屬于敏感數(shù)據(jù),我們需要密文存儲 :

查詢解密返回:

1.  自定義注解 加密標識注解  NeedEncrypt.java :

import java.lang.annotation.*;
 
/**
 * @Author JCccc
 * @Description 需加密
 * @Date 2021/7/23 11:55
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedEncrypt {
 
 
}

2.自定義注解 需加密字段標識注解 EncryptField.java :

/**
 * @Author JCccc
 * @Description
 * @Date 2021/7/23 11:55
 */
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptField {
 
    String[] value() default "";
}

3.加密邏輯的aop處理器  EncryptAspect.java :

import com.elegant.dotest.aop.annotation.EncryptField;
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.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Field;
import java.util.Objects;
 
/**
 * @Author JCccc
 * @Description
 * @Date 2021/9/14 8:55
 */
@Slf4j
@Aspect
@Component
public class EncryptAspect {
 
    @Autowired
    private StringEncryptor stringEncryptor;
 
    @Pointcut("@annotation(com.elegant.dotest.aop.annotation.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++) {
                    //拋磚引玉 ,可自行擴展其他類型字段的判斷
                    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);
                String value = stringEncryptor.encrypt(String.valueOf(field.get(obj)));
                field.set(obj, value);
            }
        }
    }
 
    /**
     * 加密單個值
     * @param realValue
     * @return
     */
    public String encryptValue(Object realValue) {
        try {
            realValue = stringEncryptor.encrypt(String.valueOf(realValue));
        } catch (Exception e) {
            log.info("加密異常={}",e.getMessage());
        }
        return String.valueOf(realValue);
    }
 
 
}

4. 插入user表 使用的 User.java :

import com.elegant.dotest.aop.annotation.EncryptField;
import lombok.Data;
import lombok.experimental.Accessors;
 
/**
 * @Author JCccc
 * @Description
 * @Date 2021/9/14 8:55
 */
@Data
@Accessors(chain = true)
public class User {
 
    private Integer id;
    private String name;
    @EncryptField
    private String phone;
    @EncryptField
    private String email;
    private Integer age;
 
}

可以看到,手機號phone 和 郵箱 email 兩個字段,我們做了注解 @EncryptField 標識:

ok,我們寫個測試接口,使用 @NeedEncrypt 注解標識這個接口需要進行加密攔截 :

使用postman調(diào)用一下測試接口:

可以看下數(shù)據(jù)庫,數(shù)據(jù)已經(jīng)加密存儲成功:

接下來是查詢解密環(huán)節(jié):

解密這里其實有些小講究。 因為查詢出來的數(shù)據(jù)有可能是單個實體,也可能是List (其實甚至是Map或者Set,又或者是 分頁數(shù)據(jù)類)

所以本文將會以 最常用的 單個實體 、 List<實體> 為例子,去做解密。

1.解密自定義注解 NeedDecrypt.java :

/**
 * @Author JCccc
 * @Description 需解密
 * @Date 2021/7/23 11:55
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedDecrypt {
 
}

2. 解密邏輯的aop處理器  DecryptAspect.java : 

import com.elegant.dotest.aop.annotation.EncryptField;
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.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
 
/**
 * @Author JCccc
 * @Description
 * @Date 2021/9/14 8:55
 */
@Slf4j
@Aspect
@Component
public class DecryptAspect {
 
    @Autowired
    private StringEncryptor stringEncryptor;
 
    @Pointcut("@annotation(com.elegant.dotest.aop.annotation.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) {
                //拋磚引玉 ,可自行擴展其他類型字段的判斷
                if (obj instanceof String) {
                    decryptValue(obj);
                } else {
                    result = decryptData(obj);
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }
 
    private Object decryptData(Object obj) throws IllegalAccessException {
 
        if (Objects.isNull(obj)) {
            return null;
        }
        if (obj instanceof ArrayList) {
            decryptList(obj);
        } else {
            decryptObj(obj);
        }
 
 
        return obj;
    }
 
    /**
     * 針對單個實體類進行 解密
     * @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);
                String realValue = (String) field.get(obj);
                String value = stringEncryptor.decrypt(realValue);
                field.set(obj, value);
            }
        }
    }
 
    /**
     * 針對list<實體來> 進行反射、解密
     * @param obj
     * @throws IllegalAccessException
     */
    private void decryptList(Object obj) throws IllegalAccessException {
        List<Object> result = new ArrayList<>();
        if (obj instanceof ArrayList) {
            for (Object o : (List<?>) obj) {
                result.add(o);
            }
        }
        for (Object object : result) {
            decryptObj(object);
        }
    }
 
 
    public String decryptValue(Object realValue) {
        try {
            realValue = stringEncryptor.encrypt(String.valueOf(realValue));
        } catch (Exception e) {
            log.info("解密異常={}", e.getMessage());
        }
        return String.valueOf(realValue);
    }
 
 
}

然后我們對一個查詢方法進行測試 :


我們先試一下查詢單條數(shù)據(jù)的:

使用@NeedDecrypt注解標記這個接口需要數(shù)據(jù)解密:

調(diào)用接口看看結(jié)果:

然后是多條數(shù)據(jù)List<User> 返回的接口:

調(diào)用接口測試看看結(jié)果:

到此這篇關(guān)于Springboot AOP對指定敏感字段數(shù)據(jù)加密存儲的實現(xiàn)的文章就介紹到這了,更多相關(guān)數(shù)據(jù)加密存儲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA運行SpringBoot項目的超詳細步驟截圖

    IDEA運行SpringBoot項目的超詳細步驟截圖

    在當(dāng)前的開發(fā)中Spring Boot開發(fā)框架已經(jīng)成為主流,下面這篇文章主要給大家介紹了關(guān)于IDEA運行SpringBoot項目的超詳細步驟截圖,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • WebsocketClient斷線的一些常見原因及解決辦法

    WebsocketClient斷線的一些常見原因及解決辦法

    這篇文章主要給大家介紹了關(guān)于WebsocketClient斷線的一些常見原因及解決辦法,文中通過代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用WebsocketClient斷線具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-12-12
  • 使用InputStream的available()能否用來判斷當(dāng)前流是否讀取到文件

    使用InputStream的available()能否用來判斷當(dāng)前流是否讀取到文件

    這篇文章主要介紹了使用InputStream的available()能否用來判斷當(dāng)前流是否讀取到文件問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • JPA findById方法和getOne方法的區(qū)別說明

    JPA findById方法和getOne方法的區(qū)別說明

    這篇文章主要介紹了JPA findById方法和getOne方法的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。
    2021-08-08
  • java中子類繼承父類,程序運行順序的深入分析

    java中子類繼承父類,程序運行順序的深入分析

    本篇文章是對java中子類繼承父類,程序運行順序進行了詳細的分析介紹,需要的朋友參考下
    2013-06-06
  • SpringBoot處理大量請求數(shù)據(jù)的傳輸問題的方法小結(jié)

    SpringBoot處理大量請求數(shù)據(jù)的傳輸問題的方法小結(jié)

    在Spring?Boot項目常常需要中處理大量請求數(shù)據(jù)的傳輸問題,這篇文章主要為大家整理了一些常用的方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • Java中Arraylist動態(tài)擴容方法詳解

    Java中Arraylist動態(tài)擴容方法詳解

    ArrayList的列表對象實質(zhì)上是存儲在一個引用型數(shù)組里的,下面這篇文章主要給大家介紹了關(guān)于Java中Arraylist動態(tài)擴容方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-08-08
  • Java?策略模式?if-else用法實例詳解

    Java?策略模式?if-else用法實例詳解

    這篇文章主要介紹了Java?策略模式?if-else用法詳解,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-07-07
  • 一文精通Java中的volatile關(guān)鍵字

    一文精通Java中的volatile關(guān)鍵字

    volatile是java中的關(guān)鍵詞之一,這篇文章主要給大家介紹了關(guān)于Java中volatile關(guān)鍵字的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • java外賣訂餐系統(tǒng)小項目

    java外賣訂餐系統(tǒng)小項目

    這篇文章主要為大家詳細介紹了java外賣訂餐系統(tǒng)小項目,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01

最新評論

海门市| 德江县| 邹平县| 永修县| 洛浦县| 孙吴县| 大名县| 招远市| 伊吾县| 太和县| 邹城市| 辽宁省| 赞皇县| 辰溪县| 稻城县| 夹江县| 万宁市| 邹平县| 乐安县| 邵武市| 宣化县| 萨迦县| 湛江市| 彭州市| 青川县| 彭泽县| 高尔夫| 綦江县| 云安县| 汤阴县| 合作市| 临安市| 珠海市| 桓台县| 张家口市| 汾阳市| 靖边县| 左云县| 南江县| 忻州市| 宁安市|