欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot中隨機鹽值+雙重SHA256加密實戰(zhàn)

 更新時間:2024年07月09日 10:00:33   作者:MoCrane  
本文主要介紹了SpringBoot中隨機鹽值+雙重SHA256加密實戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1.SHA-256和Salt

1.1.什么是SHA-256

SHA-256是一種信息摘要算法,也是一種密碼散列函數(shù)。對于任意長度的消息,SHA256都會產(chǎn)生一個256bit長的散列值(哈希值),用于確保信息傳輸完整一致,稱作消息摘要。這個摘要相當(dāng)于是個長度為32個字節(jié)的數(shù)組,通常用一個長度為64的十六進制字符串來表示。

SHA-256的具備以下幾個關(guān)鍵特點:

  • 固定長度輸出:無論輸入數(shù)據(jù)的大小,SHA-256都會產(chǎn)生一個256位(32字節(jié))的固定長度散列值。
  • 不可逆性:SHA-256的設(shè)計使得從生成的散列值無法還原原始輸入數(shù)據(jù)。這種不可逆性在安全性上是非常重要的。
  • 抗碰撞性:找到兩個不同的輸入數(shù)據(jù)具有相同的散列值(碰撞)是極其困難的。雖然理論上碰撞可能發(fā)生,但SHA-256被設(shè)計得非常抗碰撞。

除了SHA-256之外,還有一個密碼散列函數(shù)MD5,過去也常被用于密碼加密,但MD5在安全性上低于SHA-256,現(xiàn)在已經(jīng)很少用于密碼加密了,本文不做考慮。

SHA-256 和 MD5 的比較:

特性SHA-256MD5
輸出長度256 位(64 個十六進制字符)128 位(32 個十六進制字符)
安全性
計算速度較慢
抗碰撞能力
應(yīng)用場景數(shù)據(jù)完整性校驗、數(shù)字簽名、密碼存儲、區(qū)塊鏈曾用于文件校驗、密碼存儲
推薦使用

1.2.什么是隨機鹽值

鹽值(salt) 是一種在密碼學(xué)和安全計算中常用的隨機數(shù)據(jù),用于增強密碼散列的安全性。

隨機鹽值(random salt)是一種用于增強密碼散列安全性的技術(shù)。它是一個隨機生成的數(shù)據(jù)塊,在將密碼輸入散列函數(shù)之前,將鹽值與密碼組合。通過引入隨機鹽值,可以有效地防止彩虹表攻擊和相同密碼散列值重復(fù)的問題。

鹽值的作用:

  • 防止彩虹表攻擊: 彩虹表是一個預(yù)計算的哈希值數(shù)據(jù)庫,用于快速查找常見密碼的哈希值。通過在密碼哈希之前加入隨機鹽值,即使密碼相同,其最終的哈希值也會不同,從而使彩虹表無效。
  • 避免散列值重復(fù): 如果兩個用戶使用相同的密碼,在沒有鹽值的情況下,他們的哈希值會相同。加入鹽值后,即使密碼相同,生成的哈希值也會不同,這有助于防止攻擊者通過觀察哈希值來推測用戶是否使用了相同的密碼。
  • 增加攻擊難度: 鹽值增加了密碼哈希的復(fù)雜性。即使攻擊者獲取了存儲的哈希值和鹽值,他們?nèi)孕鑼γ總€鹽值進行單獨的破解,顯著增加了破解的時間和計算成本。

1.3.如何進行加密操作

本文采用的加密方式是在前端采用md加密防止明文傳輸,后端對密碼二次加密后再進行隨機鹽值的混入。

2.前端實現(xiàn)

引入md5.min.js

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登錄</title>
    <!-- jquery -->
    <script type="text/javascript" th:src="@{/js/jquery.min.js}"></script>
    <!-- bootstrap -->
    <link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/bootstrap.min.css}" rel="external nofollow" />
    <script type="text/javascript" th:src="@{/bootstrap/js/bootstrap.min.js}"></script>
    <!-- jquery-validator -->
    <script type="text/javascript" th:src="@{/jquery-validation/jquery.validate.min.js}"></script>
    <script type="text/javascript" th:src="@{/jquery-validation/localization/messages_zh.min.js}"></script>
    <!-- md5.js -->
    <script type="text/javascript" th:src="@{/js/md5.min.js}"></script>
    <!-- common.js -->
    <script type="text/javascript" th:src="@{/js/common.js}"></script>
</head>
<body>
<form name="loginForm" id="loginForm" method="post" style="width:50%; margin:0 auto">

    <h2 style="text-align:center; margin-bottom: 20px">用戶登錄</h2>

    <div class="form-group">
        <div class="row">
            <label class="form-label col-md-4">請輸入手機號碼</label>
            <div class="col-md-5">
                <input id="mobile" minlength="11" maxlength="11" name="mobile" class="form-control" type="text" placeholder="手機號碼" required="true"/>
            </div>
        </div>
    </div>

    <div class="form-group">
        <div class="row">
            <label class="form-label col-md-4">請輸入密碼</label>
            <div class="col-md-5">
                <input id="password" name="password" class="form-control" type="password" placeholder="密碼" required="true" />
            </div>
        </div>
    </div>

    <div class="row">
        <div class="col-md-5">
            <button class="btn btn-primary btn-block" type="reset" onclick="reset()">重置</button>
        </div>
        <div class="col-md-5">
            <button class="btn btn-primary btn-block" type="submit" onclick="login()">登錄</button>
        </div>
    </div>
</form>
</body>
<script>
    function login() {
        $("#loginForm").validate({
            submitHandler: function (form) {
                doLogin();
            }
        });
    }

    function doLogin() {
        var inputPass = $("#password").val();
        var salt = "1a2b3c4d";
        var str = "" + salt.charAt(0) + salt.charAt(2) + inputPass + salt.charAt(5) + salt.charAt(4);
        var password = md5(str);

        $.ajax({
            url: "/login/doLogin",
            type: "POST",
            data: {
                mobile: $("#mobile").val(),
                password: password
            },
            success: function (data) {
                layer.closeAll();
                if (data.code == 200) {
                    layer.msg("成功");
                    console.log(data);
                    document.cookie = "userTicket=" + data.object;
                    window.location.href = "/goods/toList";
                } else {
                    layer.msg(data.message);
                }
            },
            error: function () {
                layer.closeAll();
            }
        });
    }
</script>
</html>

3.后端實現(xiàn)

3.1.導(dǎo)入Maven依賴

 <dependency>
     <groupId>commons-codec</groupId>
     <artifactId>commons-codec</artifactId>
     <version>1.15</version>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

3.2.密碼加密

3.2.1.密碼加鹽

首先使用Apache的RandomStringUtils工具類,生成16位的鹽值。然后將鹽拼接到明文后面,進行SHA256加密。

這個加密后的SHA256是個固定64長度的字符串。

// 生成一個16位的隨機數(shù),也就是鹽
String salt = RandomStringUtils.randomAlphanumeric(16);

// 將鹽拼接到明文后,并生成新的sha256碼
String sha256Hex = DigestUtils.sha256Hex(password + salt);

3.2.2.隨機鹽值混合

加鹽后的SHA256碼長度為80位,這里我們采用的鹽值混合規(guī)則:將SHA-256散列值的每四個字符中間插入一個鹽值字符,依次交替排列。

// 將鹽混到新生成的SHA-256碼中,之所以這樣做是為了后期解密,校驗密碼
StringBuilder sb = new StringBuilder(80); // SHA-256是64個字符,加16個字符的鹽,總共80個字符
for (int i = 0; i < 16; i++) {
    sb.append(sha256Hex.charAt(i * 4));
    sb.append(salt.charAt(i));
    sb.append(sha256Hex.charAt(i * 4 + 1));
    sb.append(sha256Hex.charAt(i * 4 + 2));
    sb.append(sha256Hex.charAt(i * 4 + 3));
}
return sb.toString();

這樣就完成了加密的操作:密碼加鹽 + 鹽值混合。

3.3.密碼解密

3.3.1.提取鹽值和加鹽密碼

按照加密時采用的規(guī)則:將SHA-256散列值的每四個字符中間插入一個鹽值字符,依次交替排列。

我們可以將鹽值和加鹽后的SHA-256碼

// 提取鹽值和加鹽后的SHA-256碼
StringBuilder sb1 = new StringBuilder(64);
StringBuilder sb2 = new StringBuilder(16);

for (int i = 0; i < 16; i++) {
    sb1.append(encrypted.charAt(i * 5));
    sb1.append(encrypted.charAt(i * 5 + 2));
    sb1.append(encrypted.charAt(i * 5 + 3));
    sb1.append(encrypted.charAt(i * 5 + 4));
    sb2.append(encrypted.charAt(i * 5 + 1));
}

String sha256Hex = sb1.toString();
String salt = sb2.toString();

3.3.2.比較密碼

最后,將取出的鹽值與原始密碼再次加鹽,再次得到加鹽密碼,與sha256Hex比較即可判斷密碼是否相同。

// 比較二者是否相同
return  DigestUtils.sha256Hex(password + salt).equals(sha256Hex);

3.4.完整工具類

public class SHA256Util {

    /**
     * 加密
     * 生成鹽和加鹽后的SHA-256碼,并將鹽混入到SHA-256碼中,對SHA-256密碼進行加強
     **/
    public static String encryptPassword(String password) {
        // 生成一個16位的隨機數(shù),也就是鹽
        String salt = RandomStringUtils.randomAlphanumeric(16);

        // 將鹽拼接到明文后,并生成新的sha256碼
        String sha256Hex = DigestUtils.sha256Hex(password + salt);

        // 將鹽混到新生成的SHA-256碼中,之所以這樣做是為了后期解密,校驗密碼
        StringBuilder sb = new StringBuilder(80); // SHA-256是64個字符,加16個字符的鹽,總共80個字符
        for (int i = 0; i < 16; i++) {
            sb.append(sha256Hex.charAt(i * 4));
            sb.append(salt.charAt(i));
            sb.append(sha256Hex.charAt(i * 4 + 1));
            sb.append(sha256Hex.charAt(i * 4 + 2));
            sb.append(sha256Hex.charAt(i * 4 + 3));
        }
        return sb.toString();
    }

    /**
     * 解密
     * 從混入鹽的SHA-256碼中提取鹽值和加鹽后的SHA-256碼
     **/
    public static boolean verifyPassword(String password, String encrypted) {
        // 提取鹽值和加鹽后的SHA-256碼
        StringBuilder sb1 = new StringBuilder(64);
        StringBuilder sb2 = new StringBuilder(16);

        for (int i = 0; i < 16; i++) {
            sb1.append(encrypted.charAt(i * 5));
            sb1.append(encrypted.charAt(i * 5 + 2));
            sb1.append(encrypted.charAt(i * 5 + 3));
            sb1.append(encrypted.charAt(i * 5 + 4));
            sb2.append(encrypted.charAt(i * 5 + 1));
        }

        String sha256Hex = sb1.toString();
        String salt = sb2.toString();

        // 比較二者是否相同
        return  DigestUtils.sha256Hex(password + salt).equals(sha256Hex);
    }
}

到此這篇關(guān)于SpringBoot中隨機鹽值+雙重SHA256加密實戰(zhàn)的文章就介紹到這了,更多相關(guān)SpringBoot 隨機鹽值+雙重SHA256加密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Spring整合WebSocket應(yīng)用示例(上)

    Spring整合WebSocket應(yīng)用示例(上)

    以下教程是小編在參與開發(fā)公司的一個crm系統(tǒng),整理些相關(guān)資料,在該系統(tǒng)中有很多消息推送功能,在其中用到了websocket技術(shù)。下面小編整理分享到腳本之家平臺供大家參考
    2016-04-04
  • Java中自定義泛型方法及其應(yīng)用示例代碼

    Java中自定義泛型方法及其應(yīng)用示例代碼

    泛型方法是Java中一個強大的特性,它允許我們在方法級別使用類型參數(shù),提高代碼的復(fù)用性和類型安全性,通過本文,讀者可以學(xué)習(xí)如何定義和使用泛型方法,并了解其在處理集合、比較對象、創(chuàng)建實例等任務(wù)中的應(yīng)用,感興趣的朋友一起看看吧
    2025-02-02
  • Maven解決jar包版本沖突的4種方法詳解

    Maven解決jar包版本沖突的4種方法詳解

    這篇文章主要給大家介紹了關(guān)于Maven解決jar包版本沖突的4種方法代碼,maven工程要導(dǎo)入jar包的坐標(biāo),就必須要考慮解決jar包沖突,文中介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • Spring?Cloud?Ribbon?負(fù)載均衡使用策略示例詳解

    Spring?Cloud?Ribbon?負(fù)載均衡使用策略示例詳解

    Spring?Cloud?Ribbon?是基于Netflix?Ribbon?實現(xiàn)的一套客戶端負(fù)載均衡工具,Ribbon客戶端組件提供了一系列的完善的配置,如超時,重試等,這篇文章主要介紹了Spring?Cloud?Ribbon?負(fù)載均衡使用策略示例詳解,需要的朋友可以參考下
    2023-03-03
  • SpringBoot預(yù)加載與懶加載實現(xiàn)方法超詳細講解

    SpringBoot預(yù)加載與懶加載實現(xiàn)方法超詳細講解

    Spring一直被詬病啟動時間慢,可Spring/SpringBoot是輕量級的框架。因為當(dāng)Spring項目越來越大的時候,在啟動時加載和初始化Bean就會變得越來越慢,很多時候我們在啟動時并不需要加載全部的Bean,在調(diào)用時再加載就行,那這就需要預(yù)加載與懶加載的功能了
    2022-11-11
  • Mybatis中使用updateBatch進行批量更新

    Mybatis中使用updateBatch進行批量更新

    這篇文章主要介紹了Mybatis中使用updateBatch進行批量更新的相關(guān)資料,有逐條更新,sql批量更新等,具體實例代碼大家參考下本文
    2018-04-04
  • 詳解解密Java中的類型轉(zhuǎn)換問題

    詳解解密Java中的類型轉(zhuǎn)換問題

    這篇文章主要介紹了Java中的類型轉(zhuǎn)換問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 深入探究Java中的HashMap為什么會產(chǎn)生死循環(huán)

    深入探究Java中的HashMap為什么會產(chǎn)生死循環(huán)

    HashMap?死循環(huán)發(fā)生在?JDK?1.8?之前的版本中,這篇文章主要來和大家深入探究一下為什么Java中HashMap會產(chǎn)生死循環(huán),感興趣的小伙伴可以了解一下
    2023-05-05
  • IntelliJ IDEA : .java文件左下角顯示

    IntelliJ IDEA : .java文件左下角顯示"J"圖標(biāo)的問題

    IntelliJ IDEA : .java文件 左下角顯示“J”,并且不能執(zhí)行代碼,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2020-10-10
  • JAVA根據(jù)ip地址獲取歸屬地的實現(xiàn)方法

    JAVA根據(jù)ip地址獲取歸屬地的實現(xiàn)方法

    本文主要介紹了JAVA根據(jù)ip地址獲取歸屬地的實現(xiàn)方法,要通過Java程序獲取IP地址對應(yīng)的城市,需要借助第三方的IP地址庫,下面就來介紹一下,感興趣的可以了解一下
    2023-10-10

最新評論