激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

云服務(wù)器|WEB服務(wù)器|FTP服務(wù)器|郵件服務(wù)器|虛擬主機(jī)|服務(wù)器安全|DNS服務(wù)器|服務(wù)器知識(shí)|Nginx|IIS|Tomcat|

服務(wù)器之家 - 服務(wù)器技術(shù) - 服務(wù)器知識(shí) - 保護(hù)敏感數(shù)據(jù):Spring Boot中敏感字段加密解密的高效解決方案

保護(hù)敏感數(shù)據(jù):Spring Boot中敏感字段加密解密的高效解決方案

2024-01-02 08:38未知服務(wù)器之家 服務(wù)器知識(shí)

前言 相信大家都有這樣一個(gè)煩惱,就是經(jīng)常會(huì)接到各種推銷、廣告的電話和短信,如果你沒有在他那里留下過聯(lián)系方式,他又是如何得到了你的聯(lián)系方式呢?毫無疑問,是個(gè)人信息被泄漏了。個(gè)人信息的泄漏有人為不合法謀利的因

前言

相信大家都有這樣一個(gè)煩惱,就是經(jīng)常會(huì)接到各種推銷、廣告的電話和短信,如果你沒有在他那里留下過聯(lián)系方式,他又是如何得到了你的聯(lián)系方式呢?毫無疑問,是個(gè)人信息被泄漏了。個(gè)人信息的泄漏有人為不合法謀利的因素,也有系統(tǒng)不合理的安全設(shè)計(jì)造成泄漏的因素。當(dāng)然系統(tǒng)設(shè)計(jì)的角度出發(fā),敏感信息需要加密存儲(chǔ)的,數(shù)據(jù)展示的時(shí)候也要進(jìn)行相應(yīng)的脫敏處理,但是從一些關(guān)于個(gè)信息泄漏的新聞報(bào)道來看,有好多的網(wǎng)站后臺(tái)竟然是“裸奔”狀態(tài),簡(jiǎn)直太可怕了。其實(shí)敏感數(shù)據(jù)的處理也不復(fù)雜,說到底是安全意識(shí)不強(qiáng)。當(dāng)然,這篇文章和大家分享的重點(diǎn)是加密和解密的方法,不是數(shù)據(jù)安全的重要性。

基本概念

敏感數(shù)據(jù)

敏感數(shù)據(jù)是指那些泄漏后可能會(huì)給社會(huì)或個(gè)人造成嚴(yán)重危害的數(shù)據(jù),以個(gè)人隱私信息為例,如手機(jī)號(hào)碼、家庭住址、郵箱、身份證號(hào)、銀行卡帳號(hào)、購(gòu)物網(wǎng)站的支付密碼、登陸密碼等等。另外從社會(huì)的角度出發(fā),也有很多數(shù)據(jù)是屬于敏感數(shù)據(jù),如:居民的生物基因信息等等。

數(shù)據(jù)加密

數(shù)據(jù)加密是指對(duì)數(shù)據(jù)重新編碼來保護(hù)數(shù)據(jù),獲取實(shí)際數(shù)據(jù)的唯一辦法就是使用密鑰解密數(shù)據(jù);

數(shù)據(jù)解密

數(shù)據(jù)解密與數(shù)據(jù)加密是相對(duì)的,即使用密鑰對(duì)加密的數(shù)據(jù)進(jìn)行解密的過程;

加密方式

加密的方式,一般是兩種:對(duì)稱加密和非對(duì)稱加密;

對(duì)稱加密只有一個(gè)秘鑰,加密和解密都是用同一個(gè)秘鑰,如AES、DES等;

非對(duì)稱加密有兩個(gè)秘鑰,一個(gè)是公鑰,一個(gè)是私鑰。使用公鑰對(duì)數(shù)據(jù)進(jìn)行加密,加密后的數(shù)據(jù)只有私鑰可以解密,一般公鑰是公開的,私鑰是不公開的;如RSA、DSA等;

實(shí)現(xiàn)原理

Springboot項(xiàng)目中,客戶端通過接口向服務(wù)端讀取或?qū)懭朊舾袛?shù)據(jù)時(shí),常會(huì)有這樣的業(yè)務(wù)需求:

1、在客戶端向服務(wù)器端發(fā)起寫入請(qǐng)求,服務(wù)端需要對(duì)寫入的敏感數(shù)據(jù)進(jìn)行加密后存儲(chǔ);

2、在客戶端從服務(wù)器端向外讀取數(shù)據(jù)的時(shí)候,需要對(duì)輸出的敏感數(shù)據(jù)進(jìn)行解密;

顯然這種場(chǎng)景,對(duì)于加密的方式的選擇,對(duì)稱加密是最好的選擇;那么如何實(shí)現(xiàn)對(duì)寫入請(qǐng)求、讀取請(qǐng)求的敏感數(shù)據(jù)的加密、解密處理呢?解決方案如下:

1、自定義兩個(gè)切面注解,分別是加密切面注解、解密切面注解,作用于需要加密或解密的敏感數(shù)據(jù)處理的業(yè)務(wù)處理類的具體業(yè)務(wù)處理方法上;

2、自定義兩個(gè)敏感字段處理注解,分別是加密字段注解、解密字段注解,作用于需要輸入或輸出的對(duì)象的敏感字段上;如果輸入對(duì)象上標(biāo)記了加密字段注解,則表示該字段在對(duì)內(nèi)寫入數(shù)據(jù)庫(kù)的時(shí)候,需要加密處理;同理,如果輸出對(duì)象上標(biāo)記了解密字段注解,則表示該字段在對(duì)外輸出的時(shí)候,需要進(jìn)行解密;

3、使用面向切面編程,定義兩個(gè)切面類,分別是加密切面類和解密切面類,選擇Spring AOP的環(huán)繞通知來具體實(shí)現(xiàn);加密切面類中,以注解的方式定義切入點(diǎn),用到的注解就是自定義的加密切面注解;

4、如果新增、編輯等寫入類的業(yè)務(wù)請(qǐng)求處理方法上標(biāo)記了加密切面注解,那么寫入請(qǐng)求在正式被業(yè)務(wù)處理方法處理前,會(huì)命中加密切面類,加密切面類的環(huán)繞通知方法被觸發(fā),然后根據(jù)輸入的參數(shù)對(duì)象中的字段是否標(biāo)記了自定義的加密字段注解,來決定是否對(duì)當(dāng)前字段進(jìn)行加密處理;

5、同理,如果是查詢等讀取類的業(yè)務(wù)請(qǐng)求處理方法上標(biāo)記了解密切面注解,那么讀取請(qǐng)求被業(yè)務(wù)處理類處理完之后,會(huì)命中解密切面類,解密切面類的環(huán)繞通知方法被觸發(fā),然后根據(jù)返回對(duì)象的字段是否標(biāo)記了解密字段注解,來決定是否對(duì)當(dāng)前字段進(jìn)行解密處理。

保護(hù)敏感數(shù)據(jù):Spring Boot中敏感字段加密解密的高效解決方案

實(shí)現(xiàn)方案

環(huán)境配置

jdk版本:1.8開發(fā)工具:Intellij iDEA 2020.1

springboot:2.3.9.RELEASE

mybatis-spring-boot-starter:2.1.4

依賴配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.3.3</version>
</dependency>

示例時(shí)序圖

保護(hù)敏感數(shù)據(jù):Spring Boot中敏感字段加密解密的高效解決方案圖片

示例代碼

1、自定義四個(gè)注解:@DecryptField(解密字段注解)、@EncryptField(加密字段注解)、@NeedEncrypt(解密切面注解)、@NeedEncrypt(加密切面注解),其中@DecryptField作用于需要解密的字段上;@EncryptField作用于需要加密的字段上;@NeedEncrypt作用于需要對(duì)入?yún)?shù)進(jìn)行加密處理的方法上;@NeedDecrypt作用于需要對(duì)返回值進(jìn)行解密處理的方法上;

//解密字段注解
@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DecryptField {
}
//加密字段注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptField {
}
//作用于對(duì)返回值進(jìn)行解密處理的方法上
@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedDecrypt {
}
//作用于需要對(duì)入?yún)?shù)進(jìn)行加密處理的方法上
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedEncrypt {
}

2、把自定義的加密字段注解、解密字段注解標(biāo)記在需要加密或者解密的字段上;這里表示在寫入人員的手機(jī)號(hào)碼、身份證號(hào)碼、家庭住址門牌號(hào)碼時(shí),要進(jìn)行加密處理;在讀取人員的手機(jī)號(hào)碼、身份證號(hào)碼、家庭住址門牌號(hào)碼時(shí),要進(jìn)行解密處理;

@Slf4j
@Data
public class Person  {
 private Integer id;
 private String userName;
 private String loginNo;
 @EncryptField
 @DecryptField
 private String phoneNumber;
 private String sex;
 @DecryptField
 @EncryptField
 private String IDCard;
 private String address;
 @EncryptField
 @DecryptField
 private String houseNumber;
}

3、把@NeedEncrypt和@NeedDecrypt標(biāo)記在需要對(duì)入?yún)?shù)、返回值中的敏感字段進(jìn)行加密、解密處理的業(yè)務(wù)處理方法上;

@RestController
@RequestMapping("/person")
@Slf4j
public class PersonController {
    @Autowired
    private IPersonService personService;
    //添加人員信息
    @PostMapping("/add")
    @NeedEncrypt
    public Person add(@RequestBody Person person, Model model) {
        Person result = this.personService.registe(person);
        log.info("http://增加person執(zhí)行完成");
        return result;
    }
    //人員信息列表查詢
    @GetMapping("/list")
    @NeedDecrypt
    public List<Person> getPerson() {
        List<Person> persons = this.personService.getPersonList();
        log.info("http://查詢person列表執(zhí)行完成");
        return persons;
    }
    //人員信息詳情查詢
    @GetMapping("/{id}")
    @NeedDecrypt
    public Person get(@PathVariable Integer id) {
        Person persnotallow= this.personService.get(id);
        log.info("http://查詢person詳情執(zhí)行完成");
        return person;
    }
}

4、自定義加密切面類(EncryptAop)和解密切面類(DecryptAop):用@NeedEncrypt注解定義加密切點(diǎn),在加密切點(diǎn)的環(huán)繞通知方法里執(zhí)行到具體的業(yè)務(wù)處理方法之前,判斷輸入對(duì)象的參數(shù)字段是否標(biāo)記了@EncryptField(加密字段注解),如果判斷結(jié)果為true,則使用java反射對(duì)該字段進(jìn)行加密處理,注意這里引用了hutool的工具包,使用了工具包里的加密和解密方法,這里也可以替換成其他的方式;用@NeedDecrypt注解定義解密切點(diǎn),在解密切點(diǎn)的環(huán)繞通知方法里執(zhí)行完具體的業(yè)務(wù)處理方法之后,判斷輸出對(duì)象的參數(shù)字段是否標(biāo)記了@DecryptField(解密字段注解),如果判斷結(jié)果為true,則使用java反射對(duì)該 字段進(jìn)行解密處理;

@Component
@Aspect
@Slf4j
public class EncryptAop {
    /**
     * 定義加密切入點(diǎn)
     */
    @Pointcut(value = "@annotation(com.fanfu.anno.NeedEncrypt)")
    public void pointcut() {
    }


    /**
     * 命中加密切入點(diǎn)的環(huán)繞通知
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("http://環(huán)繞通知 start");
        //獲取命中目標(biāo)方法的入?yún)?shù)
        Object[] args = proceedingJoinPoint.getArgs();
        if (args.length > 0) {
            for (Object arg : args) {
                //按參數(shù)的類型進(jìn)行判斷,如果業(yè)務(wù)中還有其他的類型,可酌情增加
                if (arg != null) {
                    if (arg instanceof List) {
                        for (Object tmp : ((List) arg)) {
                            //加密處理
                            this.deepProcess(tmp);
                        }
                    } else {
                        this.deepProcess(arg);
                    }
                }
            }
        }
        //對(duì)敏感數(shù)據(jù)加密后執(zhí)行目標(biāo)方法
        Object result = proceedingJoinPoint.proceed();
        log.info("http://環(huán)繞通知 end");
        return result;
    }


    public void deepProcess(Object obj) throws IllegalAccessException {
        if (obj != null) {
            //獲取對(duì)象的所有字段屬性并遍歷
            Field[] declaredFields = obj.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                //判斷字段屬性上是否標(biāo)記了@EncryptField注解
                if (declaredField.isAnnotationPresent(EncryptField.class)) {
                    //如果判斷結(jié)果為真,則取出字段屬性值,進(jìn)行加密、重新賦值
                    declaredField.setAccessible(true);
                    Object valObj = declaredField.get(obj);
                    if (valObj != null) {
                        String value = valObj.toString();
                        //開始敏感字段屬性值加密
                        String decrypt = this.encrypt(value);
                        //把加密后的字段屬性值重新賦值
                        declaredField.set(obj, decrypt);
                    }
                }
            }
        }
    }


    private String encrypt(String value) {
        //這里特別注意一下,對(duì)稱加密是根據(jù)密鑰進(jìn)行加密和解密的,加密和解密的密鑰是相同的,一旦泄漏,就無秘密可言,
        //“fanfu-csdn”就是我自定義的密鑰,這里僅作演示使用,實(shí)際業(yè)務(wù)中,這個(gè)密鑰要以安全的方式存儲(chǔ);
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue(), "fanfu-csdn".getBytes()).getEncoded();
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.DES, key);
        String encryptValue = aes.encryptBase64(value);
        return encryptValue;
    }


}
@Component
@Aspect
@Slf4j
public class DecryptAop {
    /**
     * 定義需要解密的切入點(diǎn)
     */
    @Pointcut(value = "@annotation(com.fanfu.anno.NeedDecrypt)")
    public void pointcut() {
    }


    /**
     * 命中的切入點(diǎn)時(shí)的環(huán)繞通知
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("http://環(huán)繞通知 start");
        //執(zhí)行目標(biāo)方法
        Object result = proceedingJoinPoint.proceed();
        //判斷目標(biāo)方法的返回值類型
        if (result instanceof List) {
            for (Object tmp : ((List) result)) {
                //數(shù)據(jù)脫敏處理邏輯
                this.deepProcess(tmp);
            }
        } else {
            this.deepProcess(result);
        }
        log.info("http://環(huán)繞通知 end");
        return result;
    }


    public void deepProcess(Object obj) throws IllegalAccessException {
        if (obj != null) {
            //取出輸出對(duì)象的所有字段屬性,并遍歷
            Field[] declaredFields = obj.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                //判斷字段屬性上是否標(biāo)記DecryptField注解
                if (declaredField.isAnnotationPresent(DecryptField.class)) {
                    //如果判斷結(jié)果為真,則取出字段屬性數(shù)據(jù)進(jìn)行解密處理
                    declaredField.setAccessible(true);
                    Object valObj = declaredField.get(obj);
                    if (valObj != null) {
                        String value = valObj.toString();
                        //加密數(shù)據(jù)的解密處理
                        value = this.decrypt(value);
                        DecryptField annotation = declaredField.getAnnotation(DecryptField.class);
                        boolean open = annotation.open();
                        //把解密后的數(shù)據(jù)重新賦值
                        declaredField.set(obj, value);
                    }
                }
            }
        }
    }


    private String decrypt(String value) {
        //這里特別注意一下,對(duì)稱加密是根據(jù)密鑰進(jìn)行加密和解密的,加密和解密的密鑰是相同的,一旦泄漏,就無秘密可言,
        //“fanfu-csdn”就是我自定義的密鑰,這里僅作演示使用,實(shí)際業(yè)務(wù)中,這個(gè)密鑰要以安全的方式存儲(chǔ);
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue(), "fanfu-csdn".getBytes()).getEncoded();
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.DES, key);
        String decryptStr = aes.decryptStr(value);
        return decryptStr;
    }
}

加密結(jié)果

保護(hù)敏感數(shù)據(jù):Spring Boot中敏感字段加密解密的高效解決方案圖片

解密結(jié)果

保護(hù)敏感數(shù)據(jù):Spring Boot中敏感字段加密解密的高效解決方案圖片

總結(jié)

這篇著重和大家分享的內(nèi)容如下:

1、敏感數(shù)據(jù)的一些基礎(chǔ)概念;

2、敏感數(shù)據(jù)處理的解決思路;

3、敏感數(shù)據(jù)處理的具體實(shí)現(xiàn)方式;

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久艹艹艹| 成人资源在线观看 | 久久久久亚洲视频 | av日韩一区二区三区 | 极品xxxx欧美一区二区 | 亚洲卡通动漫在线观看 | 色999久久久精品人人澡69 | jizzjizz中国少妇中文 | 日本视频网 | 久久欧美亚洲另类专区91大神 | 免费中文视频 | 精品国产一区二区三区四区在线 | 日韩毛片一区二区三区 | 一级成人欧美一区在线观看 | 色天天综合网 | www.com国产精品 | 国产99久久久久久免费看 | 国产精品一区二区免费在线观看 | 欧洲成人免费视频 | 国产精品成人一区二区三区吃奶 | 久色网站 | 精品国产精品久久 | 国产精品久久久久免费视频 | 欧美成人免费在线视频 | 在线观看福利网站 | 久久精品国产清自在天天线 | 久久久www成人免费毛片 | 国产扩阴视频 | 午夜免费一区 | 亚洲资源在线 | 国产精品视频免费网站 | 亚洲国产成人一区 | 久久最新免费视频 | 海角在线观看91一区二区 | 视频一区二区不卡 | 久久成年网 | 日韩黄a | 免费国产成人高清在线看软件 | 国产色片 | 久久婷婷一区二区三区 | 最近日本电影hd免费观看 |