目錄
自己實現?
?Spring Security
MappedByteBuffer
RandomAccess
加鹽加密的實現
自己實現?
傳統MD5可通過彩虹表暴力破解,?
加鹽加密算法是一種常用的密碼保護方法,它將一個隨機字符串(鹽)添加到原始密碼中,然后再進行加密處理。
- 1. 每次調用方法產生一個唯一鹽值(UUID )+密碼=最終密碼。
- 解密:需要驗證的密碼(用戶輸入的密碼),最終加密的密碼(存在于數據庫)得到鹽值,鹽值存在最終密碼的某個位置,——>鹽值{32位}$最終密碼{32位};
- ?2. 對組合后的字符串進行多次哈希計算,每次哈希時都使用鹽值和先前的哈希值。哈希計算的次數由工作因子控制。
驗證密碼
已有:用戶輸入的明文密碼、此用戶在數據庫存儲的最終密碼=[鹽值$加密后的密碼]
32位32位
1.從最終密碼中得到鹽值
2.將用戶輸入的明文密碼+鹽值進行加密操作=加密后的密碼3.使用鹽值+分隔符+加密后的密碼生成數據庫存儲的密碼
4.對比生成的最終密碼和數據庫最終的密碼是否相等如果相等,那么用戶名和密碼就是對的,反之則是密碼輸入錯誤。?
package com.example.demo.common;import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;import java.nio.charset.StandardCharsets;
import java.util.UUID;public class PasswordUtils {//1.加鹽生成密碼public static String encrypt(String password){//鹽32位String salt= UUID.randomUUID().toString().replace("-","");String saltPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());String finalPassword=salt+"$"+saltPassword;return finalPassword;}//2.生成加鹽密碼public static String encrypt(String password,String salt){String saltPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes());String finalPassword=salt+"$"+saltPassword;return finalPassword;}/**驗證密碼** @param :用戶輸入的明文密碼* @param :數據庫保存的最終密碼* @return*/public static boolean check(String inputPassword , String finalPassword){if(StringUtils.hasLength(inputPassword)&&StringUtils.hasLength(finalPassword)&&finalPassword.length()==65){String salt=finalPassword.split("\\$")[0];String confirmPssword=PasswordUtils.encrypt(inputPassword,salt);return confirmPssword.equals(finalPassword);}return false;}public static void main(String[] args) {String password="123456";String finalPassword=encrypt(password);System.out.println(PasswordUtils.encrypt(password));String inputPassword="12345";String inputPassword2="123456";System.out.println("比對結果1:"+ check(inputPassword,finalPassword));System.out.println("比對結果2 :"+ check(inputPassword2,finalPassword));//check(inputPassword2,finalPassword);}
}
?
?Spring Security
是提供身份驗證和授權的框架?,可用于用戶認證,訪問控制,安全事件和日志記錄等
還有就是Spring Security加鹽
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>
?這樣甚至改了頁面
當用這個認證密碼授權成功后才會到我們的登錄頁面
所以我們要排除SpringSecurity自動加載
?
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
package com.example.demo;import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;@SpringBootTest()
class Demo1ApplicationTests {@Testvoid contextLoads() {BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();String password ="123456";// 第一次加密String finalPassword1 = passwordEncoder.encode(password);System.out.println("第1次加密:" + finalPassword1);// 第二次加密String finalPassword2 = passwordEncoder.encode(password);System.out.println("第2次加密:" + finalPassword2);// 第三次加密String finalPassword3 = passwordEncoder.encode(password);System.out.println("第3次加密:" + finalPassword3);// 驗證密碼String inputPassword = "12345";System.out.println("錯誤密碼比對結果: " + (passwordEncoder.matches(inputPassword, finalPassword1)));String inputPassword2 = "123456";System.out.println("正確密碼比對結果: " + (passwordEncoder.matches(inputPassword2, finalPassword1)));}}
?
MappedByteBuffer
MappedByteBuffer 是 Java NIO 包提供的一種用于內存映射文件的緩沖區類型。它可以將文件的一部分或整個文件映射到內存中,以便進行更高效的讀寫操作。
使用 MappedByteBuffer 的步驟如下:
1. 獲取文件通道:通過 RandomAccessFile、FileInputStream 或 FileChannel 等方式獲取文件的 FileChannel 對象。
2. 創建 MappedByteBuffer:使用 `map()` 方法將文件的一部分或整個文件內容映射到內存中,并返回一個 MappedByteBuffer 對象。
?? ?MappedByteBuffer mappedBuffer = channel.map(FileChannel.MapMode.READ_WRITE, position, size);
- channel 是 FileChannel 對象,表示要映射的文件通道。
- FileChannel.MapMode.READ_WRITE 表示映射模式,可選擇的模式有:
- READ_ONLY:只讀模式,映射的數據不能進行修改。
- READ_WRITE:讀寫模式,映射的數據可進行讀寫操作。
- PRIVATE:私有模式,對映射的數據的修改不會影響到原文件。
- position 是要映射的文件位置,表示從文件的哪個位置開始映射。
- size 是映射的大小,表示映射的字節數。
3. 通過 MappedByteBuffer 對象進行讀寫操作:可以通過 MappedByteBuffer 對象的方法進行數據的讀取和寫入,如 get(), put(), getChar(), putChar()`等。
4. 關閉文件通道和釋放資源:在不再使用時,需要關閉文件通道和釋放 MappedByteBuffer 對象相關的資源。
?? ?? ?channel.close();
MappedByteBuffer 只是對文件內容進行了內存映射,并不會自動將修改的數據寫回到原文件。如果需要將修改的數據同步到磁盤上的文件,可以通過調用 MappedByteBuffer 的 `force()` 方法強制刷新緩沖區。
使用 MappedByteBuffer 可以實現高效的文件讀寫操作,尤其適用于對大文件進行隨機訪問和修改的場景。
?
在Java中,處理大文件時常用的有基于`MappedByteBuffer`的NIO(New I/O)和基于`BufferedInputStream`、`BufferedOutputStream`等帶緩沖的傳統IO流。下面是它們之間的一些區別和相對優勢:
1. 內存映射文件(MappedByteBuffer):
? ?- **優勢**:
? ? ?- 避免了數據在Java堆內存和本地內存的多次拷貝,提高了IO操作的效率。
? ? ?- 可以利用操作系統的虛擬內存機制,對文件進行部分映射,實現了按需加載,對于大文件的處理性能更好。
? ? ?- 適合隨機訪問,可以直接在內存中修改文件內容,不需要通過讀取和寫入的方式。
? ?- **劣勢**:
? ? ?- 需要謹慎管理內存映射,避免內存泄漏和資源未釋放的問題。
? ? ?- 對于頻繁讀寫的大文件,可能會導致內存占用過高。2. 緩沖流(BufferedInputStream、BufferedOutputStream):
? ?- **優勢**:
? ? ?- 通過緩沖區減少了對底層IO系統調用的次數,提高了IO操作效率。
? ? ?- 可以適應各種大小的文件讀寫,并且易于使用。
? ? ?- 適合順序讀寫,對于較小的文件處理效率較高。
? ?- **劣勢**:
? ? ?- 在處理大文件時,需要在Java和操作系統之間來回拷貝數據,可能會導致性能瓶頸。
? ? ?- 不支持直接在內存中修改文件內容,需要通過讀取和寫入的方式來進行操作。綜上所述,對于大文件的處理,基于`MappedByteBuffer`的NIO操作相對于傳統的緩沖流操作具有更高的性能和更少的內存開銷,特別是在需要隨機訪問大文件內容時,`MappedByteBuffer`更為適用。但需要注意合理管理內存映射,避免潛在的風險。而基于緩沖流的傳統IO操作適用于各種大小的文件處理,易于使用,但在處理大文件時可能會存在性能瓶頸。
RandomAccess
RandomAccessFile 類是 Java IO 包中的一個用于隨機訪問文件的工具類,它可以讀取或寫入文件的任意位置。與其他 IO 類不同,RandomAccessFile 可以支持對文件內容的隨機讀寫操作,并且可以通過指定文件指針的位置實現隨機訪問。
使用 RandomAccessFile 類進行文件操作的常見步驟如下:
1. 創建 RandomAccessFile 對象,需要指定文件路徑和打開模式("r" 表示只讀,"rw" 表示讀寫)。
?RandomAccessFile raf = new RandomAccessFile("file.txt", "rw");
2. 使用 RandomAccessFile 提供的方法進行讀寫操作:
?? ?- `read()`:從當前文件指針位置讀取一個字節的數據并將文件指針后移。- `write(int b)`:將一個字節的數據寫入到當前文件指針位置,并將文件指針后移。- `read(byte[] buffer)`:從當前文件指針位置讀取指定長度的字節數組數據,并將文件指針后移相應的字節數。- `write(byte[] buffer)`:將指定長度的字節數組數據寫入到當前文件指針位置,并將文件指針后移相應的字節數。- `seek(long position)`:將文件指針移動到指定的位置。
3. 在完成文件讀寫操作后,需要關閉 RandomAccessFile 對象,釋放資源。
??raf.close();
RandomAccessFile 類提供了一些靈活的方法來操作文件,但也需要謹慎處理文件指針位置和邊界條件,以避免讀寫錯誤或越界訪問。另外,RandomAccessFile 類通常用于處理二進制文件,而不是用于處理文本文件。在讀取文本文件時,可以使用更方便的 BufferedReader 或 Scanner 類。
RandomAccessFile更適合小文件,支持多線程,適合靈活隨機讀取文件的各個部分。
MapperdByteBuffer:適合大文件,將文件映射到內存來處理文件,直接訪問內存,避免頻繁對磁盤進行io操作,