Spring Boot + Vue 基于 RSA 的用戶身份認(rèn)證加密機(jī)制實(shí)現(xiàn)過程
Spring Boot + Vue 基于 RSA 的用戶身份認(rèn)證加密機(jī)制實(shí)現(xiàn)
什么是RSA?
RSA算法是一種非對(duì)稱加密算法,與對(duì)稱加密算法不同的是,RSA算法有兩個(gè)不同的密鑰,一個(gè)是公鑰,一個(gè)是私鑰
RSA公開密鑰密碼體制是一種使用不同的加密密鑰與解密密鑰,“由已知加密密鑰推導(dǎo)出解密密鑰在計(jì)算上是不可行的”密碼體制
在公開密鑰密碼體制中,加密密鑰(即公開密鑰)PK是公開信息,而解密密鑰(即秘密密鑰)SK是需要保密的。加密算法E和解密算法D也都是公開的。雖然解密密鑰SK是由公開密鑰PK決定的,但卻不能根據(jù)PK計(jì)算出SK
正是基于這種理論,1978年出現(xiàn)了著名的RSA算法,它通常是先生成一對(duì)RSA密鑰,其中之一是保密密鑰,由用戶保存;另一個(gè)為公開密鑰,可對(duì)外公開,甚至可在網(wǎng)絡(luò)服務(wù)器中注冊(cè)。為提高保密強(qiáng)度,RSA密鑰至少為500位長(zhǎng)。這就使加密的計(jì)算量很大。為減少計(jì)算量,在傳送信息時(shí),常采用傳統(tǒng)加密方法與公開密鑰加密方法相結(jié)合的方式,即信息采用改進(jìn)的DES或IDEA對(duì)話密鑰加密,然后使用RSA密鑰加密對(duì)話密鑰和信息摘要。對(duì)方收到信息后,用不同的密鑰解密并可核對(duì)信息摘要
安全需求介紹
背景:在安全掃描過程中,系統(tǒng)被檢測(cè)到存在中危漏洞,影響了用戶登錄環(huán)節(jié)的信息安全性
漏洞描述
Web程序在處理用戶登錄過程中,針對(duì)用戶名和口令在傳輸前未采用加密。用戶名和口令一旦被惡意攻擊者嗅探或暴力破解得到后,可以直接利用它去登錄系統(tǒng)。
解決方案:建議對(duì)用戶名、口令等參數(shù)值采用強(qiáng)加密算法,如SHA512、RSA、AES、國(guó)密算法等,避免使用MD5、Base64、DES、3DES等弱算法。
問題分析:未加密的敏感信息在傳輸過程中易被攔截,尤其是在公共網(wǎng)絡(luò)環(huán)境下。這使得系統(tǒng)的認(rèn)證機(jī)制成為攻擊目標(biāo),存在較高的安全隱患
需求實(shí)現(xiàn):
- 在前端使用安全加密算法對(duì)用戶名和密碼進(jìn)行加密,防止信息裸露傳輸
- 后端解密用戶信息并進(jìn)行驗(yàn)證,同時(shí)保障傳輸數(shù)據(jù)的完整性與安全性
前后端交互流程

基于RSA加密的登錄流程,Web端和服務(wù)端的交互過程詳細(xì)步驟:
- 用戶發(fā)起登錄請(qǐng)求:
- 用戶在Web端輸入登錄操作,Web端開始處理登錄流程
- Web端向服務(wù)端發(fā)送一個(gè)請(qǐng)求,要求獲取RSA加密所需的公鑰
- 服務(wù)端返回公鑰:
- 服務(wù)端接收到公鑰請(qǐng)求后,從系統(tǒng)中讀取公鑰信息,并將公鑰發(fā)送回Web端。這個(gè)步驟的響應(yīng)無需校驗(yàn)
- Web端加密用戶憑據(jù):
- Web端使用獲取到的公鑰,對(duì)用戶的用戶名和密碼進(jìn)行加密。加密后的數(shù)據(jù)用于安全傳輸,避免敏感信息在網(wǎng)絡(luò)中被截獲
- Web端將加密后的用戶名和密碼通過HTTPS協(xié)議發(fā)送給服務(wù)端。HTTPS協(xié)議提供了額外的安全層,防止中間人攻擊
- 服務(wù)端解密并驗(yàn)證:
- 服務(wù)端接收到加密的數(shù)據(jù)后,使用私鑰對(duì)加密內(nèi)容進(jìn)行解密。私鑰是嚴(yán)格保密的,只在服務(wù)端保存和使用服務(wù)端對(duì)解密后的用戶名和密碼進(jìn)行驗(yàn)證,檢查憑據(jù)是否正確并符合登錄要求
- 返回登錄結(jié)果:
- 服務(wù)端驗(yàn)證完成后,將登錄驗(yàn)證的結(jié)果返回給Web端。結(jié)果可以是登錄成功或失敗的信息
- Web端處理響應(yīng):
- Web端接收并處理服務(wù)端返回的登錄結(jié)果,并顯示相應(yīng)的提示或進(jìn)行后續(xù)操作
前端使用 RSA 加密密碼
在前端 Vue.js 中,使用 jsencrypt 庫(kù)對(duì)用戶名密碼進(jìn)行加密,并將加密后的用戶名密碼發(fā)送給后端
安裝 jsencrypt庫(kù)
在Vue.js 項(xiàng)目中運(yùn)行以下命令來安裝 jsencrypt:
npm install jsencrypt --save
實(shí)現(xiàn)敏感信息加密
在 Vue.js 登錄頁(yè)面中,對(duì)敏感信息進(jìn)行加密,然后發(fā)送給后端:
// 引入 jsencrypt 和 Base64 編碼庫(kù)
import JSEncrypt from 'jsencrypt';
// 需要安裝 js-base64 庫(kù)
import { Base64 } from 'js-base64';
export default {
data() {
return {
username: '', // 用戶輸入的用戶名
password: '' // 用戶輸入的密碼
};
},
methods: {
/**
* 使用 RSA 公鑰加密字符串
* @param {string} str - 需要加密的字符串
* @returns {string|null} - 加密后的字符串,若失敗返回 null
*/
encryptString(str) {
// 初始化 JSEncrypt
const encrypt = new JSEncrypt();
// 設(shè)置公鑰
const publicKey = `
-----BEGIN PUBLIC KEY-----
...公鑰內(nèi)容...
-----END PUBLIC KEY-----
`;
encrypt.setPublicKey(publicKey);
// 加密字符串并返回加密結(jié)果
return encrypt.encrypt(str);
},
/**
* 用戶登錄邏輯
*/
login() {
// 獲取用戶輸入的用戶名和密碼
const username = this.username.trim(); // 去除多余空格
const password = this.password.trim();
// 驗(yàn)證用戶名和密碼是否為空
if (!username || !password) {
this.$message.error('用戶名或密碼不能為空'); // 提示用戶
return;
}
// 加密用戶名和密碼
const encryptedUsername = this.encryptString(username);
const encryptedPassword = this.encryptString(password);
// 驗(yàn)證加密是否成功
if (!encryptedUsername || !encryptedPassword) {
this.$message.error('加密失敗,請(qǐng)檢查公鑰配置');
return;
}
// Base64 編碼的主要作用是將加密后的數(shù)據(jù)轉(zhuǎn)換成由可見 ASCII 字符組成的字符串,以便在網(wǎng)絡(luò)傳輸或存儲(chǔ)時(shí)避免因特殊字符引發(fā)的兼容性問題
const base64EncodedUsername = Base64.encode(encryptedUsername);
const base64EncodedPassword = Base64.encode(encryptedPassword);
// 發(fā)送登錄請(qǐng)求到后端
this.$axios.post('/api/login', {
username: base64EncodedUsername, // 加密后的用戶名
password: base64EncodedPassword // 加密后的密碼
}).then(response => {
// 登錄成功后的處理邏輯
if (response.data.success) {
this.$message.success('登錄成功');
// 跳轉(zhuǎn)到主頁(yè)面或其他邏輯
} else {
this.$message.error(response.data.message || '登錄失敗');
}
}).catch(error => {
// 請(qǐng)求失敗的處理邏輯
console.error('登錄請(qǐng)求失敗:', error);
this.$message.error('登錄失敗,請(qǐng)稍后重試');
});
}
}
};服務(wù)器端生成RSA的公私鑰文件
Windows環(huán)境 生成rsa的公私鑰文件
安裝 OpenSSL:下載并安裝 OpenSSL for Windows,可以從 OpenSSL 官網(wǎng) 下載適合的版本。

生成 RSA 私鑰:
- 在安裝目錄的bin目錄下面,打開命令提示符(
cmd) - 運(yùn)行以下命令生成一個(gè)2048位的私鑰文件
private_key.pem:
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048

- 生成 RSA 公鑰:
- 使用生成的私鑰來提取公鑰,運(yùn)行以下命令:
openssl rsa -pubout -in private_key.pem -out public_key.pem

?
Linux環(huán)境 生成rsa的公私鑰文件
使用RSA算法生成pem格式的私鑰文件,指定密鑰長(zhǎng)度2048
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
使用RSA算法在上述私鑰文件基礎(chǔ)上生成pem格式的公鑰文件
openssl rsa -pubout -in private_key.pem -out public_key.pem
執(zhí)行完成后,會(huì)看到輸出兩份文件 private_key.pem, public_key.pem。
后端代碼實(shí)現(xiàn)
返回給前端的公鑰接口
將生成的兩份密鑰文件放入指定的目錄中,然后在配置文件中配置公私鑰文件所屬路徑
/**
* 獲取公鑰
*/
@GetMapping("/getPublicKey")
public AjaxResult getPublicKey() {
// 加載資源
File file = new File("公鑰的文件所屬路徑");
if (!file.exists()) {
throw new BusinessException("未獲取到指定公鑰文件");
}
String publicKey;
try (InputStream inputStream = Files.newInputStream(file.toPath())) {
publicKey = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
} catch (IOException e) {
log.error("讀取公鑰文件失敗", e);
// 返回錯(cuò)誤信息
return AjaxResultGenerator.error("讀取公鑰文件失敗");
}
// 檢查 publicKey 是否為 null 或空字符串
if (publicKey == null || publicKey.isEmpty()) {
return AjaxResultGenerator.error("公鑰內(nèi)容為空");
}
// 刪除PEM格式的頭部和尾部以及所有空格、換行符
publicKey = publicKey.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replaceAll("\\s+", "");
return AjaxResultGenerator.success(publicKey);
}解密前端傳入的加密字符串
前端的賬戶和密碼進(jìn)行rsa加密并且base64編碼后,調(diào)用正常登錄接口login(),readPrivateKeyAndDecode()方法將 RSA 加密并 Base64 編碼的字符串解碼后,再用 RSA 私鑰對(duì)解碼后的數(shù)據(jù)進(jìn)行解密,最終返回解密后的原始數(shù)據(jù)
pom.xml
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency>
登錄和解密方法
/**
* 用戶名密碼登錄
*
* @param loginBody 登錄信息
* @return 結(jié)果
*/
@PostMapping("/v1/login")
public AjaxResult login(@RequestBody LoginBody loginBody) {
// 使用 RSA 私鑰解密
String username = readPrivateKeyAndDecode(loginBody.getUsername());
String password = readPrivateKeyAndDecode(loginBody.getPassword());
loginBody.setUsername(username);
loginBody.setPassword(password);
// 執(zhí)行正常的登錄邏輯...
return AjaxResultGenerator.success();
}
/**
* 讀取私鑰并解密
*
* @param rsaEncoded64Str 已rsa加密并且base64編碼后的字符串
* @return
*/
public String readPrivateKeyAndDecode(String rsaEncoded64Str) {
// 加載資源
File file= new File("私鑰的文件所屬路徑");
if (!file.exists()) {
throw new BusinessException("未獲取到指定私鑰文件");
}
String privateKey;
try (InputStream inputStream = Files.newInputStream(file.toPath())) {
privateKey = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
} catch (IOException e) {
log.error("讀取私鑰文件失敗", e);
throw new BusinessException("讀取私鑰文件失?。? + e.getMessage());
}
if (StringUtils.isBlank(privateKey)) {
throw new BusinessException("私鑰內(nèi)容為空");
}
// 刪除PEM格式的頭部和尾部以及所有空格、換行符
privateKey = privateKey.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
// 進(jìn)行base64解密
String decodedUsername = new String(Base64.getDecoder().decode(rsaEncoded64Str));
// 使用 RSA 私鑰解密,用到了hutool-all中的類
return new RSA(privateKey, null)
.decryptStr(decodedUsername, KeyType.PrivateKey);
}實(shí)現(xiàn)效果

到此這篇關(guān)于Spring Boot + Vue 基于 RSA 的用戶身份認(rèn)證加密機(jī)制實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Spring Boot Vue 身份認(rèn)證加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java線程池實(shí)戰(zhàn)應(yīng)用步驟詳解
這篇文章主要介紹了java線程池實(shí)戰(zhàn)應(yīng)用小結(jié),包括線程池的創(chuàng)建方式,本文給大家分享兩種方式,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2025-04-04
Java 實(shí)戰(zhàn)項(xiàng)目之疫情人員流動(dòng)管理系統(tǒng)詳解
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java實(shí)現(xiàn)一個(gè)疫情人員流動(dòng)管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11
hibernate通過session實(shí)現(xiàn)增刪改查操作實(shí)例解析
這篇文章主要介紹了hibernate通過session實(shí)現(xiàn)增刪改查操作實(shí)例解析,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12
Java WebSocket客戶端接收大量數(shù)據(jù)的三種方案
WebSocket是一種基于TCP協(xié)議的全雙工通信協(xié)議,它能夠在客戶端和服務(wù)器之間建立一個(gè)持久連接,實(shí)現(xiàn)實(shí)時(shí)的雙向數(shù)據(jù)傳輸,在實(shí)際應(yīng)用中,有時(shí)候我們需要處理大量的數(shù)據(jù),所以本文將介紹如何使用 Java WebSocket 客戶端接收大量數(shù)據(jù),并提供一些優(yōu)化方案2023-11-11
Spring boot 在idea中添加熱部署插件的圖文教程
這篇文章主要介紹了Spring boot 在idea中添加熱部署插件的圖文教程,本文通過圖文并茂的形式給大家展示具體步驟,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
springboot 整合fluent mybatis的過程,看這篇夠了
這篇文章主要介紹了springboot 整合fluent mybatis的過程,配置數(shù)據(jù)庫(kù)連接創(chuàng)建數(shù)據(jù)庫(kù)的詳細(xì)代碼,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08
詳解SpringMVC加載配置Properties文件的幾種方式
這篇文章主要介紹了詳解SpringMVC加載配置Properties文件的幾種方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02

