0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Spring Boot如何優(yōu)雅實(shí)現(xiàn)數(shù)據(jù)加密存儲(chǔ)、模糊匹配和脫敏

冬至子 ? 來(lái)源:Shepherd進(jìn)階筆記 ? 作者:Shepherd ? 2023-06-19 14:42 ? 次閱讀

1.概述

近來(lái)我們都在圍繞著使用Spring Boot開(kāi)發(fā)業(yè)務(wù)系統(tǒng)時(shí)如何保證數(shù)據(jù)安全性這個(gè)主題展開(kāi)總結(jié),當(dāng)下大部分的B/S架構(gòu)的系統(tǒng)也都是基于Spring Boot + SpringMVC三層架構(gòu)開(kāi)發(fā)的,可以認(rèn)為是在SpringMVC的三層架構(gòu)中的controller層(邏輯控制層)對(duì)接口數(shù)據(jù)進(jìn)行安全處理操作,更直接點(diǎn)說(shuō)就是在接口請(qǐng)求參數(shù)傳入進(jìn)行邏輯處理或者響應(yīng)參數(shù)輸出到頁(yè)面展示之前就是數(shù)據(jù)處理的,所以只是在SpringMVC三層架構(gòu)中的一層中進(jìn)行安全加固,還不是很穩(wěn)固,接下來(lái)今天我們就再來(lái)講講在SpringMVC三層架構(gòu)另一層中如何進(jìn)行數(shù)據(jù)安全加固,在今天主題之前先來(lái)看看什么是SpringMVC架構(gòu)?

什么是SpringMVC三層架構(gòu)?

SpringMVC的工程結(jié)構(gòu)一般來(lái)說(shuō)分為三層,自下而上是Modle層(模型,數(shù)據(jù)訪問(wèn)層)、Cotroller層(控制,邏輯控制層)、View層(視圖,頁(yè)面顯示層),其中Modle層分為兩層:dao層、service層,MVC架構(gòu)分層的主要作用是解耦。采用分層架構(gòu)的好處,普遍接受的是系統(tǒng)分層有利于系統(tǒng)的維護(hù),系統(tǒng)的擴(kuò)展。就是增強(qiáng)系統(tǒng)的可維護(hù)性和可擴(kuò)展性。對(duì)于Spring這樣的框架,(View\\Web)表示層調(diào)用控制層(Controller),控制層調(diào)用業(yè)務(wù)層(Service),業(yè)務(wù)層調(diào)用數(shù)據(jù)訪問(wèn)層(Dao) 可以這么說(shuō),現(xiàn)在90%以上的業(yè)務(wù)系統(tǒng)都是基于該三層架構(gòu)模式開(kāi)發(fā)的,這種架構(gòu)模式也有人說(shuō)是設(shè)計(jì)模式中一種,可見(jiàn)其重要性不言而喻,所以我們需重視。

我們也都知道在日常開(kāi)發(fā)系統(tǒng)過(guò)程中,數(shù)據(jù)安全是非常重要的。特別是在當(dāng)今互聯(lián)網(wǎng)時(shí)代,個(gè)人隱私安全極其重要,一旦個(gè)人用戶數(shù)據(jù)遭到攻擊泄露,將會(huì)造成災(zāi)難級(jí)的事故問(wèn)題。所有之前我們基于接口層進(jìn)行數(shù)據(jù)安全處理是遠(yuǎn)遠(yuǎn)不夠的,今天我們就來(lái)談?wù)勅绾蜯odel層(數(shù)據(jù)訪問(wèn)層)怎樣做到優(yōu)雅數(shù)據(jù)加密存儲(chǔ)、模糊匹配及其脫敏展示,本文的主題: 數(shù)據(jù)加密存儲(chǔ)、模糊匹配和脫敏展示 。

銀行系統(tǒng)對(duì)數(shù)據(jù)安全性的要求在業(yè)務(wù)系統(tǒng)中是首屈一指的,所以今天我們就以常見(jiàn)的個(gè)人銀行賬戶數(shù)據(jù):密碼、手機(jī)號(hào)、詳細(xì)地址、銀行卡號(hào)等信息字段為例,進(jìn)行主題的宣講與淺析。

2.數(shù)據(jù)加密存儲(chǔ)

我們之前總結(jié)的是在接口層進(jìn)行數(shù)據(jù)加解密傳輸,也強(qiáng)調(diào)過(guò)這種方式保證不了數(shù)據(jù)的絕對(duì)安全,只是有效提高接口數(shù)據(jù)安全性,抬高數(shù)據(jù)被抓取的門檻而已。所以接下來(lái)我們就來(lái)講述一下如何在數(shù)據(jù)的源頭存儲(chǔ)層保障其安全。我們都知道一些核心私密字段,比如說(shuō)密碼,手機(jī)號(hào)等在數(shù)據(jù)庫(kù)層存儲(chǔ)就不能明文存儲(chǔ),必須加密存儲(chǔ)保證即使數(shù)據(jù)庫(kù)泄露了也不會(huì)輕易曝光數(shù)據(jù)。

2.1 優(yōu)雅實(shí)現(xiàn)數(shù)據(jù)庫(kù)字段加解密原理

Mybatis-plus提供企業(yè)高級(jí)特性就有支持?jǐn)?shù)據(jù)加密解密,不過(guò)是收費(fèi)的。。。但是我們可以細(xì)細(xì)探究其原理進(jìn)行功能的自我實(shí)現(xiàn)。

其實(shí)在我們上面推薦的快速開(kāi)發(fā)框架中就已經(jīng)優(yōu)雅整合了數(shù)據(jù)加解密功能了,EncryptTypeHandler:實(shí)現(xiàn)數(shù)據(jù)庫(kù)的字段加密與解密。

默認(rèn)提供了基于base64加密算法Base64EncryptService和AES加密算法AESEncryptService,當(dāng)然業(yè)務(wù)側(cè)也可以自定義加密算法,這需要實(shí)現(xiàn)接口EncryptService,并把實(shí)現(xiàn)類注入到容器中即可。加密功能核心邏輯

@Bean
@ConditionalOnMissingBean(EncryptService.class)
public EncryptService encryptService() {
  Algorithm algorithm = encryptProperties.getAlgorithm();
  EncryptService encryptService;
  switch (algorithm) {
    case BASE64:
      encryptService =  new Base64EncryptService();
      break;
    case AES:
      encryptService = new AESEncryptService();
      break;
    default:
      encryptService =  null;
  }
  return encryptService;
}

接下來(lái)就可以基于加密算法,擴(kuò)展mybatis的typeHandler對(duì)實(shí)體字段數(shù)據(jù)進(jìn)行加密解密了:EncryptTypeHandler

public class EncryptTypeHandler< T > extends BaseTypeHandler< T > {

    @Resource
    private EncryptService encryptService;

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, encryptService.encrypt((String)parameter));
    }
    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String columnValue = rs.getString(columnName);
        return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)encryptService.decrypt(columnValue);
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String columnValue = rs.getString(columnIndex);
        return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)encryptService.decrypt(columnValue);
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String columnValue = cs.getString(columnIndex);
        return StrUtil.isBlank(columnValue) ? (T)columnValue : (T)encryptService.decrypt(columnValue);
    }
}

2.2 加密與解密示例

首先創(chuàng)建一張user表:

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL,
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `phone` varchar(255) DEFAULT NULL COMMENT '手機(jī)號(hào)',
  `id_card` varchar(255) DEFAULT NULL COMMENT '身份證號(hào)',
  `bank_card` varchar(255) DEFAULT NULL COMMENT '銀行卡號(hào)',
  `address` varchar(255) DEFAULT NULL COMMENT '住址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

這時(shí)候我們正常插入一條數(shù)據(jù):

@Test
    public void test() {
        User user = new User();
        user.setName("shepherd");
        user.setMobile("17812345678");
        user.setIdCard("213238199601182111");
        user.setBankCard("3222022046741500");
        user.setAddress("杭州市余杭區(qū)未來(lái)科技城");
        userDAO.insert(user);
    }

數(shù)據(jù)庫(kù)存儲(chǔ)查詢結(jié)果如下:

1.jpg

這就是我們平時(shí)不加密存儲(chǔ)查詢的結(jié)果,這里id是通過(guò)分布式id算法自動(dòng)生成的哈。

接下來(lái)我們來(lái)看看實(shí)現(xiàn)對(duì)數(shù)據(jù)的加密,只需要在配置文件配置使用哪一種加密算法和在實(shí)體類的字段屬性加上注解@TableField(typeHandler = EncryptTypeHandler.class)即可。

這里我們使用aes加密算法:

ptc:
  encrypt:
    algorithm: aes

實(shí)體類:

@Data
@TableName(autoResultMap = true)
public class User {

    private Long id;
    private String name;

    @TableField(typeHandler = EncryptTypeHandler.class)
    private String mobile;
    @TableField(typeHandler = EncryptTypeHandler.class)
    private String idCard;
    @TableField(typeHandler = EncryptTypeHandler.class)
    private String bankCard;
    @TableField(typeHandler = EncryptTypeHandler.class)
    private String address;
}

再次插入數(shù)據(jù),數(shù)據(jù)庫(kù)存儲(chǔ)查詢結(jié)果如下:

1.jpg

然后我們可以測(cè)試對(duì)這條數(shù)據(jù)進(jìn)行查詢:

@Test
    public void get() {
        User user = userDAO.selectById(1567405175268642818l);
        System.out.println(user);
    }

結(jié)果如下:

User(id=1567405175268642818, name=shepherd, mobile=17812345678, idCard=213238199601182111, bankCard=3222022046741500, address=杭州市余杭區(qū)未來(lái)科技城)

基于以上完美展示了數(shù)據(jù)加密存儲(chǔ)和解密查詢。

2.3 數(shù)據(jù)加密后怎么進(jìn)行模糊匹配

密碼、手機(jī)號(hào)、詳細(xì)地址、銀行卡號(hào)這些信息對(duì)加解密的要求也不一樣,比如說(shuō)密碼我們需要加密存儲(chǔ),一般使用的都是不可逆的慢hash算法,慢hash算法可以避免暴力破解(典型的用時(shí)間換安全性)。

在檢索時(shí)我們既不需要解密也不需要模糊查找,直接使用密文完全匹配,但是手機(jī)號(hào)就不能這樣做,因?yàn)槭謾C(jī)號(hào)我們要查看原信息,并且對(duì)手機(jī)號(hào)還需要支持模糊查找,因此我們今天就針對(duì)可逆加解密的數(shù)據(jù)支持模糊查詢來(lái)看看有哪些實(shí)現(xiàn)方式。

我們接下來(lái)看看常規(guī)的做法,也是最廣泛使用的方法,此類方法及滿足的數(shù)據(jù)安全性,又對(duì)查詢友好。

在數(shù)據(jù)庫(kù)實(shí)現(xiàn)加密算法函數(shù),在模糊查詢的時(shí)候使用decode(key) like '%partial%

在數(shù)據(jù)庫(kù)中實(shí)現(xiàn)與程序一致的加解密算法,修改模糊查詢條件,使用數(shù)據(jù)庫(kù)加解密函數(shù)先解密再模糊查找,這樣做的優(yōu)點(diǎn)是實(shí)現(xiàn)成本低,開(kāi)發(fā)使用成本低,只需要將以往的模糊查找稍微修改一下就可以實(shí)現(xiàn),但是缺點(diǎn)也很明顯,這樣做無(wú)法利用數(shù)據(jù)庫(kù)的索引來(lái)優(yōu)化查詢,甚至有一些數(shù)據(jù)庫(kù)可能無(wú)法保證與程序?qū)崿F(xiàn)一致的加解密算法,但是對(duì)于常規(guī)的加解密算法都可以保證與應(yīng)用程序一致。如果對(duì)查詢性能要求不是特別高、對(duì)數(shù)據(jù)安全性要求一般,可以使用常見(jiàn)的加解密算法比如說(shuō)AES、DES之類的也是一個(gè)不錯(cuò)的選擇。

對(duì)密文數(shù)據(jù)進(jìn)行分詞組合,將分詞組合的結(jié)果集分別進(jìn)行加密,然后存儲(chǔ)到擴(kuò)展列,查詢時(shí)通過(guò)key like '%partial%' [先對(duì)字符進(jìn)行固定長(zhǎng)度的分組,將一個(gè)字段拆分為多個(gè),比如說(shuō)根據(jù)4位英文字符(半角),2個(gè)中文字符(全角)為一個(gè)檢索條件,舉個(gè)例子

shepherd使用4個(gè)字符為一組的加密方式,第一組shep ,第二組heph ,第三組ephe ,第四組pher … 依次類推。

如果需要檢索所有包含檢索條件4個(gè)字符的數(shù)據(jù)比如:pher ,加密字符后通過(guò) key like “%partial%” 查庫(kù)。

分詞加密實(shí)現(xiàn)

public static String splitValueEncrypt(String value, int splitLength) {
        //檢查參數(shù)是否合法
        if (StringUtils.isBlank(value) && splitLength <= 0) {
            return null;
        }
        String encryptValue = "";

        //獲取整個(gè)字符串可以被切割成字符子串的個(gè)數(shù)
        int n = (value.length() - splitLength + 1);

        //分詞(規(guī)則:分詞長(zhǎng)度根據(jù)【splitLength】且每次分割的開(kāi)始跟結(jié)束下標(biāo)加一)
        for (int i = 0; i < n; i++) {
            String splitValue = value.substring(i, splitLength++);
            encryptValue += encrypt(splitValue);
        }

        return encryptValue;
    }

    /**
     * 獲取加密值
     *
     * @param value 加密值
     * @return
     */
    private static String encrypt(String value) {
        // 這里進(jìn)行加密
        return  null;
    }

基于上面分詞加密保存到擴(kuò)展列,同時(shí)要求對(duì)原字段的正刪改查對(duì)需要對(duì)其相應(yīng)的擴(kuò)展列適配,還要注意由于分詞之后導(dǎo)致擴(kuò)展列的長(zhǎng)度可能是原字段幾倍甚至幾十倍,所以務(wù)必在開(kāi)發(fā)之前選擇和合適分詞長(zhǎng)度和加密算法,一旦加密開(kāi)始之后,再更改成本就較高了。像如果手機(jī)號(hào)我們只支持后8位搜索、身份證號(hào)只支持后4位搜索,這樣我們就可以通過(guò)原字段截取后面位數(shù)直接加密存儲(chǔ)到擴(kuò)展列,不需要再分詞。

3.數(shù)據(jù)脫敏

實(shí)際的業(yè)務(wù)開(kāi)發(fā)過(guò)程中,我們經(jīng)常需要對(duì)用戶的隱私數(shù)據(jù)進(jìn)行脫敏處理。所謂脫敏處理其實(shí)就是將數(shù)據(jù)進(jìn)行混淆隱藏,例如用戶手機(jī)信息展示178****5939,以免泄露個(gè)人隱私信息。

3.1實(shí)現(xiàn)思路

思路比較簡(jiǎn)單:在接口返回?cái)?shù)據(jù)之前按要求對(duì)數(shù)據(jù)進(jìn)行脫敏加工之后再返回前端。

一開(kāi)始打算用@ControllerAdvice去實(shí)現(xiàn),但發(fā)現(xiàn)需要自己去反射類獲取注解,當(dāng)返回對(duì)象比較復(fù)雜,需要遞歸去反射,性能一下子就會(huì)降低,于是換種思路,我想到平時(shí)使用的@JsonFormat,跟我現(xiàn)在的場(chǎng)景很類似,通過(guò)自定義注解跟字段解析器,對(duì)字段進(jìn)行自定義解析。

脫敏字段類型枚舉

public enum MaskEnum {
    /**
     * 中文名
     */
    CHINESE_NAME,
    /**
     * 身份證號(hào)
     */
    ID_CARD,
    /**
     * 座機(jī)號(hào)
     */
    FIXED_PHONE,
    /**
     * 手機(jī)號(hào)
     */
    MOBILE_PHONE,
    /**
     * 地址
     */
    ADDRESS,
    /**
     * 電子郵件
     */
    EMAIL,
    /**
     * 銀行卡
     */
    BANK_CARD
}

脫敏注解類 :用在脫敏字段之上

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = MaskSerialize.class)
public @interface FieldMask {

    /**
     * 脫敏類型
     * @return
     */
    MaskEnum value();
}

脫敏序列化類

public class MaskSerialize extends JsonSerializer< String > implements ContextualSerializer {

    /**
     * 脫敏類型
     */
    private MaskEnum type;


    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        switch (this.type) {
            case CHINESE_NAME:
            {
                jsonGenerator.writeString(MaskUtils.chineseName(s));
                break;
            }
            case ID_CARD:
            {
                jsonGenerator.writeString(MaskUtils.idCardNum(s));
                break;
            }
            case FIXED_PHONE:
            {
                jsonGenerator.writeString(MaskUtils.fixedPhone(s));
                break;
            }
            case MOBILE_PHONE:
            {
                jsonGenerator.writeString(MaskUtils.mobilePhone(s));
                break;
            }
            case ADDRESS:
            {
                jsonGenerator.writeString(MaskUtils.address(s, 4));
                break;
            }
            case EMAIL:
            {
                jsonGenerator.writeString(MaskUtils.email(s));
                break;
            }
            case BANK_CARD:
            {
                jsonGenerator.writeString(MaskUtils.bankCard(s));
                break;
            }
        }
    }

    @Override
    public JsonSerializer < ? > createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        // 為空直接跳過(guò)
        if (beanProperty == null) {
            return serializerProvider.findNullValueSerializer(beanProperty);
        }
        // 非String類直接跳過(guò)
        if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
            FieldMask fieldMask = beanProperty.getAnnotation(FieldMask.class);
            if (fieldMask == null) {
                fieldMask = beanProperty.getContextAnnotation(FieldMask.class);
            }
            if (fieldMask != null) {
                // 如果能得到注解,就將注解的 value 傳入 MaskSerialize
                return new MaskSerialize(fieldMask.value());
            }
        }
        return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
    }

    public MaskSerialize() {}

    public MaskSerialize(final MaskEnum type) {
        this.type = type;
    }
}

3.2使用示例

在發(fā)送短信記錄的接口上對(duì)手機(jī)號(hào)進(jìn)行脫敏:

@FieldMask(MaskEnum.MOBILE_PHONE)
    private String mobile;

調(diào)用接口返回?cái)?shù)據(jù)如下:

{
  "code": 200,
  "msg": "OK",
  "data": {
    "list": [
      {
        "id": 1565599123774607362,
        "signId": 8389008488923136,
        "templateId": 8445337328943104,
        "templateType": 1,
        "content": "可愛(ài)的${name},博客文章已于${submitTime}上傳更新,請(qǐng)抽空瀏覽。",
        "channelType": 0,
        "mobile": "178****5939",
        "sendStatus": 0,
        "receiveStatus": 0
      }
    ],
    "total": 19,
    "pages": 19
  }
}

4.總結(jié)

基于上面內(nèi)容我們總結(jié)如何在數(shù)據(jù)存儲(chǔ)層進(jìn)行數(shù)據(jù)安全加固來(lái)達(dá)到系統(tǒng)的更安全性,可以這么說(shuō)沒(méi)有最安全的系統(tǒng)只有更安全的系統(tǒng)。所以我們?cè)陂_(kāi)發(fā)歷程中都會(huì)窮極一生去加固系統(tǒng)安全性能。當(dāng)然了,加強(qiáng)系統(tǒng)安全性的方式還有很多種,我們最近只是圍繞基于Spring BootSpringMVC框架中有效優(yōu)雅地實(shí)現(xiàn)數(shù)據(jù)安全性,感興趣的小伙伴可以自行了解其他加固方式。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Hash算法
    +關(guān)注

    關(guān)注

    0

    文章

    43

    瀏覽量

    7378
  • SpringMVC
    +關(guān)注

    關(guān)注

    0

    文章

    18

    瀏覽量

    5741
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Spring Boot如何實(shí)現(xiàn)異步任務(wù)

    Spring Boot 提供了多種方式來(lái)實(shí)現(xiàn)異步任務(wù),這里介紹三種主要實(shí)現(xiàn)方式。 1、基于注解 @Async @Async 注解是 Spring
    的頭像 發(fā)表于 09-30 10:32 ?1317次閱讀

    Spring Boot Starter需要些什么

    pulsar-spring-boot-starter是非常有必要的,在此之前,我們先看看一個(gè)starter需要些什么。 Spring Boot Starter spring-boot
    的頭像 發(fā)表于 09-25 11:35 ?687次閱讀
    <b class='flag-5'>Spring</b> <b class='flag-5'>Boot</b> Starter需要些什么

    Spring Boot從零入門1 詳述

    在開(kāi)始學(xué)習(xí)Spring Boot之前,我之前從未接觸過(guò)Spring相關(guān)的項(xiàng)目,Java基礎(chǔ)還是幾年前自學(xué)的,現(xiàn)在估計(jì)也忘得差不多了吧,寫Spring
    的頭像 發(fā)表于 12-10 22:18 ?573次閱讀

    基于Spring Cloud和Euraka的優(yōu)雅下線以及灰度發(fā)布

    該方式借助的是 Spring Boot 應(yīng)用的 Shutdown hook,應(yīng)用本身的下線也是優(yōu)雅的,但如果你的服務(wù)發(fā)現(xiàn)組件使用的是 Eureka,那么默認(rèn)最長(zhǎng)會(huì)有 90 秒的延遲,其他應(yīng)用才會(huì)感知到該服務(wù)下線
    的頭像 發(fā)表于 04-20 09:52 ?1814次閱讀

    Spring Boot特有的實(shí)踐

    Spring Boot是最流行的用于開(kāi)發(fā)微服務(wù)的Java框架。在本文中,我將與你分享自2016年以來(lái)我在專業(yè)開(kāi)發(fā)中使用Spring Boot所采用的最佳實(shí)踐。這些內(nèi)容是基于我的個(gè)人經(jīng)驗(yàn)
    的頭像 發(fā)表于 09-29 10:24 ?843次閱讀

    強(qiáng)大的Spring Boot 3.0要來(lái)了

    來(lái)源:OSC開(kāi)源社區(qū)(ID:oschina2013) Spring Boot 3.0 首個(gè) RC 已發(fā)布,此外還為兩個(gè)分支發(fā)布了更新:2.7.5 2.6.13。 3.0.0-RC1: https
    的頭像 發(fā)表于 10-31 11:17 ?1557次閱讀

    用這4招 優(yōu)雅實(shí)現(xiàn)Spring Boot異步線程間數(shù)據(jù)傳遞

    Spring Boot 自定義線程池實(shí)現(xiàn)異步開(kāi)發(fā)相信看過(guò)陳某的文章都了解,但是在實(shí)際開(kāi)發(fā)中需要在父子線程之間傳遞一些數(shù)據(jù),比如用戶信息,鏈路信息等等
    的頭像 發(fā)表于 01-30 10:40 ?1080次閱讀

    Spring Boot Web相關(guān)的基礎(chǔ)知識(shí)

    Boot的第一個(gè)接口。接下來(lái)將會(huì)將會(huì)介紹使用Spring Boot開(kāi)發(fā)Web應(yīng)用的相關(guān)內(nèi)容,其主要包括使用spring-boot-starter-web組件來(lái)
    的頭像 發(fā)表于 03-17 15:03 ?592次閱讀

    簡(jiǎn)述Spring Boot數(shù)據(jù)校驗(yàn)

    上一篇文章我們了解了Spring Boot Web相關(guān)的知識(shí),初步了解了spring-boot-starter-web,還了解了@Contrler和@RestController的差別,如果
    的頭像 發(fā)表于 03-17 15:07 ?708次閱讀

    如何實(shí)現(xiàn)一個(gè)注解進(jìn)行數(shù)據(jù)脫敏

    、測(cè)試 后記 ? 本文主要分享什么是數(shù)據(jù)脫敏,如何優(yōu)雅的在項(xiàng)目中運(yùn)用一個(gè)注解實(shí)現(xiàn)數(shù)據(jù)脫敏,為項(xiàng)目
    的頭像 發(fā)表于 06-14 09:37 ?918次閱讀
    如何<b class='flag-5'>實(shí)現(xiàn)</b>一個(gè)注解進(jìn)行<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>脫敏</b>

    什么是數(shù)據(jù)脫敏?常用的脫敏規(guī)則有哪些呢?

    數(shù)據(jù)脫敏,指對(duì)某些敏感信息通過(guò)脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù)。
    的頭像 發(fā)表于 08-15 10:04 ?2.2w次閱讀
    什么是<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>脫敏</b>?常用的<b class='flag-5'>脫敏</b>規(guī)則有哪些呢?

    Spring Boot Actuator快速入門

    不知道大家在寫 Spring Boot 項(xiàng)目的過(guò)程中,使用過(guò) Spring Boot Actuator 嗎?知道 Spring
    的頭像 發(fā)表于 10-09 17:11 ?572次閱讀

    Spring Boot啟動(dòng) Eureka流程

    在上篇中已經(jīng)說(shuō)過(guò)了 Eureka-Server 本質(zhì)上是一個(gè) web 應(yīng)用的項(xiàng)目,今天就來(lái)看看 Spring Boot 是怎么啟動(dòng) Eureka 的。 Spring Boot 啟動(dòng) E
    的頭像 發(fā)表于 10-10 11:40 ?790次閱讀
    <b class='flag-5'>Spring</b> <b class='flag-5'>Boot</b>啟動(dòng) Eureka流程

    Spring Boot的啟動(dòng)原理

    可能很多初學(xué)者會(huì)比較困惑,Spring Boot 是如何做到將應(yīng)用代碼和所有的依賴打包成一個(gè)獨(dú)立的 Jar 包,因?yàn)閭鹘y(tǒng)的 Java 項(xiàng)目打包成 Jar 包之后,需要通過(guò) -classpath 屬性
    的頭像 發(fā)表于 10-13 11:44 ?581次閱讀
    <b class='flag-5'>Spring</b> <b class='flag-5'>Boot</b>的啟動(dòng)原理

    Spring Boot 的設(shè)計(jì)目標(biāo)

    什么是Spring Boot Spring BootSpring 開(kāi)源組織下的一個(gè)子項(xiàng)目,也是 S
    的頭像 發(fā)表于 10-13 14:56 ?520次閱讀
    <b class='flag-5'>Spring</b> <b class='flag-5'>Boot</b> 的設(shè)計(jì)目標(biāo)