最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot+Vue實(shí)現(xiàn)SM4加密傳輸

 更新時(shí)間:2026年02月06日 09:25:49   作者:楓葉梨花  
本文主要介紹了SpringBoot+Vue實(shí)現(xiàn)SM4加密傳輸,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

最近項(xiàng)目中因?yàn)槊鼙R?,需要對敏感?shù)據(jù)加密傳輸,目前就用SpringBoot+Vue實(shí)現(xiàn)SM4加密傳輸,目前只是一個(gè)基礎(chǔ)過渡方案,僅供參考使用。

一、前置準(zhǔn)備

1. 后端SpringBoot:引入BouncyCastle依賴

Java這邊實(shí)現(xiàn)SM4,最常用的就是BouncyCastle這個(gè)加密庫,直接在pom.xml里加依賴就行,我用的是1.70版本,比較穩(wěn)定,沒什么兼容性問題:

<dependency>
   <groupId>org.bouncycastle</groupId>
   <artifactId>bcprov-jdk15on</artifactId>
   <version>1.70</version>
</dependency>

2. 前端Vue:安裝sm4js插件

前端這邊不用自己造輪子,有現(xiàn)成的sm4js插件可以用,直接npm安裝即可,命令很簡單:

npm install sm4js

二、后端核心:SM4工具類實(shí)現(xiàn)(SpringBoot)

后端的核心就是寫一個(gè)可復(fù)用的SM4工具類,我這里實(shí)現(xiàn)了CBC模式(比ECB模式更安全,需要初始化向量IV),同時(shí)支持Base64編碼(方便網(wǎng)絡(luò)傳輸,比Hex更節(jié)省空間)。

先給大家貼完整代碼,后面再嘮關(guān)鍵要點(diǎn):

import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

import static java.util.Objects.isNull;

@Slf4j
public class SM4Utils {

    private static final int DEFAULT_KEY_SIZE = 128;
    private static final String ALGORITHM = "SM4";
    private static final String SM4_ECB_ = "SM4/ECB/";
    private static final String SM4_CBC_ = "SM4/CBC/";
    private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();
    private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder();
    private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();

    // 靜態(tài)代碼塊:注冊BouncyCastle加密提供者
    static {
        if (isNull(Security.getProvider(BouncyCastleProvider.PROVIDER_NAME))) {
            Security.addProvider(PROVIDER);
        }
    }

    // 填充模式枚舉,方便調(diào)用,常用PKCS5/PKCS7
    @Getter
    public enum Padding {
        PKCS5("PKCS5Padding"),
        PKCS7("PKCS7Padding"),
        ISO10126("ISO10126Padding");

        private final String name;

        Padding(String name) {
            this.name = name;
        }
    }

    // 生成Base64格式的SM4密鑰(128位,SM4默認(rèn)密鑰長度)
    public static String genKeyAsBase64() {
        return genKeyAsBase64(DEFAULT_KEY_SIZE);
    }

    public static String genKeyAsBase64(int keySize) {
        return BASE64_ENCODER.encodeToString(genKey(keySize));
    }

    @SneakyThrows
    private static byte[] genKey(int keySize) {
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
        kg.init(keySize, new SecureRandom());
        return kg.generateKey().getEncoded();
    }

    // CBC模式:Base64加密(核心業(yè)務(wù)方法,敏感數(shù)據(jù)傳輸用這個(gè))
    public static String encryptBase64_CBC(String data, String key) {
        // 固定IV(前后端必須一致?。?,也可以動(dòng)態(tài)生成后和密文一起傳輸
        String fixedIv = "Wqsdy3M345BV6GRXB";
        return BASE64_ENCODER.encodeToString(encrypt_CBC(
                data.getBytes(StandardCharsets.UTF_8),
                key.getBytes(StandardCharsets.UTF_8),
                fixedIv.getBytes(StandardCharsets.UTF_8),
                Padding.PKCS5
        ));
    }

    // CBC模式:底層字節(jié)數(shù)組加密實(shí)現(xiàn)
    @SneakyThrows
    private static byte[] encrypt_CBC(byte[] data, byte[] key, byte[] iv, Padding padding) {
        Cipher cipher = getCipher_CBC(padding);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        return cipher.doFinal(data);
    }

    // 獲取CBC模式的Cipher實(shí)例
    @SneakyThrows
    private static Cipher getCipher_CBC(Padding padding) {
        return Cipher.getInstance(SM4_CBC_ + padding.name, BouncyCastleProvider.PROVIDER_NAME);
    }

    // 測試方法
    public static void main(String[] args) {
        // 測試:密鑰(前后端一致,可通過genKeyAsBase64()生成)
        String key = "qwegwfdtwer234";
        // 敏感數(shù)據(jù)
        String sensitiveData = "11111";
        // 加密結(jié)果
        String encryptedData = SM4Utils.encryptBase64_CBC(sensitiveData, key);
        System.out.println("加密后的密文:" + encryptedData);
    }
}

后端關(guān)鍵要點(diǎn)說明

  1. 密鑰和IV的約定
  2. 填充模式:這里用了PKCS5Padding,和前端sm4js的默認(rèn)填充模式兼容,避免對接時(shí)出現(xiàn)填充錯(cuò)誤。
  3. Base64編碼:加密后的字節(jié)數(shù)組轉(zhuǎn)成Base64字符串,方便通過HTTP接口傳輸,不會(huì)出現(xiàn)亂碼問題。

三、前端核心:Vue實(shí)現(xiàn)SM4解密

前端的核心是接收后端返回的Base64密文,通過sm4js插件進(jìn)行解密,還原出原始的敏感數(shù)據(jù)。我這里封裝了一個(gè)工具類,方便在項(xiàng)目的各個(gè)組件中復(fù)用。

1. 可選:全局注冊sm4js(方便全局調(diào)用)

如果項(xiàng)目中很多地方都需要解密,可以在main.js里全局注冊,省去每次引入的麻煩:

import Sm4js from 'sm4js' 
Vue.prototype.$sm4 = Sm4js

2. 核心:解密工具類封裝

新建一個(gè)sm4Utils.js文件,封裝解密方法,關(guān)鍵是要和后端的密鑰、IV、加密模式、填充模式保持一致,否則解密肯定翻車:

import Sm4js from 'sm4js';

let sm4Utils = {};

// 解密方法:參數(shù)(后端約定的密鑰,后端返回的Base64密文)
sm4Utils.decryptedData = function(key, data){
    // sm4配置項(xiàng):和后端完全對應(yīng)!
    let sm4Config = {
        key: key, // 密鑰:和后端一致(qwegwfdtwer234)
        iv: 'Wqsdy3M345BV6GRXB', // IV:和后端固定IV一致
        mode: 'cbc', // 加密模式:CBC(和后端一致)
        padding: 'PKCS5Padding' // 填充模式:和后端一致(默認(rèn)也可以,保險(xiǎn)起見顯式指定)
    }
    // 實(shí)例化sm4對象
    let sm4 = new Sm4js(sm4Config);
    // 關(guān)鍵:后端返回的是Base64密文,先通過atob()解碼,再進(jìn)行sm4解密
    return sm4.decrypt(atob(data));
}

export default sm4Utils;

3. 組件中使用解密工具類

在需要解密的Vue組件中,引入封裝好的工具類,直接調(diào)用即可,非常方便:

<template>
  <div>
    <p>解密后的數(shù)據(jù):{{ decryptedResult }}</p>
  </div>
</template>

<script>
// 引入sm4解密工具類
import sm4Utils from '@/utils/sm4Utils.js';

export default {
  data() {
    return {
      decryptedResult: '', // 解密結(jié)果
      key: 'qwegwfdtwer234', // 后端約定的密鑰
      encryptedData: '' // 后端返回的加密密文(接口請求獲?。?
    };
  },
  mounted() {
    // 模擬接口返回密文,調(diào)用解密方法
    this.encryptedData = SM4Utils.encryptBase64_CBC("11111","qwegwfdtwer234"); // 后端返回的密文
    this.decryptedResult = sm4Utils.decryptedData(this.key, this.encryptedData);
  }
};
</script>

四、總結(jié)

該方案其實(shí)對數(shù)據(jù)安全傳輸提升不明顯,后期有較大的提升空間。該方案只能防止「明文傳輸被竊聽」,避免敏感數(shù)據(jù)被「零成本獲取」,是一種「基礎(chǔ)的安全防護(hù)」,比明文傳輸略強(qiáng),但存在較明顯的短板。

核心弊端

  1. 密鑰安全隱患:前端需持有密鑰,無論硬編碼還是接口獲取,均可能被提取,泄露后加密失效。
  2. 對稱加密局限:單密鑰加解密,一旦密鑰泄露,攻擊者可解密所有數(shù)據(jù)、偽造加密信息。
  3. 前端環(huán)境脆弱:瀏覽器/客戶端易被調(diào)試、抓包,輔助防護(hù)僅增加攻擊難度,無法根治泄露風(fēng)險(xiǎn)。
  4. 適用場景有限:僅能抵御基礎(chǔ)竊聽,無法滿高安全等級(jí)項(xiàng)目的保密需求。

安全提升方案

  1. 動(dòng)態(tài)生成短期密鑰:為每個(gè)用戶會(huì)話生成臨時(shí)SM4密鑰,綁定會(huì)話有效期,過期自動(dòng)失效,降低密鑰泄露影響范圍。
  2. 非對稱加密傳密鑰:用SM2/RSA加密臨時(shí)SM4密鑰,前端僅存公鑰(可公開),后端保管私鑰,杜絕密鑰傳輸泄露。
  3. 密鑰安全存儲(chǔ)與清理:前端密鑰不存localStorage,僅駐留內(nèi)存,會(huì)話結(jié)束(退出/關(guān)頁)立即清空,避免殘留。
  4. 增加數(shù)據(jù)校驗(yàn)機(jī)制:后端對加密數(shù)據(jù)添加SM3哈希校驗(yàn),前端解密后驗(yàn)證,防止數(shù)據(jù)被篡改偽造。
  5. 前端代碼加固:開啟代碼混淆、禁止調(diào)試、密鑰分片存儲(chǔ),提升攻擊者提取密鑰和破解邏輯的難度。
  6. 接口權(quán)限與加密結(jié)合:對獲取密鑰/密文的接口做嚴(yán)格權(quán)限控制,僅授權(quán)用戶可訪問,多重防護(hù)降低風(fēng)險(xiǎn)。

到此這篇關(guān)于SpringBoot+Vue實(shí)現(xiàn)SM4加密傳輸?shù)奈恼戮徒榻B到這了,更多相關(guān)SpringBoot Vue SM4加密傳輸內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java8中的Collectors.groupingBy用法詳解

    java8中的Collectors.groupingBy用法詳解

    這篇文章主要介紹了java8中的Collectors.groupingBy用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java統(tǒng)計(jì)接口耗時(shí)的常用方法大全

    Java統(tǒng)計(jì)接口耗時(shí)的常用方法大全

    線上接口突然變慢,用戶投訴不斷,但你卻不知道問題出在哪里?今天我就來分享6種統(tǒng)計(jì)接口耗時(shí)的實(shí)用方法,幫你快速定位性能瓶頸,需要的朋友可以參考下
    2026-01-01
  • springboot各種下載文件的方式匯總

    springboot各種下載文件的方式匯總

    下載功能其實(shí)就是用戶輸入指定文件路徑信息,然后把文件返回給用戶,下面這篇文章主要給大家介紹了關(guān)于springboot各種下載文件的方式,需要的朋友可以參考下
    2022-10-10
  • 一文帶你入門SpringMVC的配置與使用

    一文帶你入門SpringMVC的配置與使用

    Spring MVC是Spring Framework的一部分,是基于Java實(shí)現(xiàn)MVC的輕量級(jí)Web框架。本文將通過一些簡單示例帶大家掌握SpringMVC的配置與使用,感興趣的可以了解一下
    2022-11-11
  • 深入了解Java核心類庫--BigDecimal和System類

    深入了解Java核心類庫--BigDecimal和System類

    這篇文章主要為大家詳細(xì)介紹了javaBigDecimal和System類定義與使用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助
    2021-07-07
  • Java從入門到精通之旅類和對象全面解析

    Java從入門到精通之旅類和對象全面解析

    Java是一門純面向?qū)ο蟮恼Z言(OOP),在面向?qū)ο蟮氖澜缋?一切皆為對象,面向?qū)ο笫墙鉀Q問題的一種思想,主要依靠對象之間的交互完成一件事情,這篇文章主要介紹了Java從入門到精通之旅類和對象全面解析,需要的朋友可以參考下
    2025-04-04
  • Java 重命名 Excel 工作表并設(shè)置工作表標(biāo)簽顏色的示例代碼

    Java 重命名 Excel 工作表并設(shè)置工作表標(biāo)簽顏色的示例代碼

    這篇文章主要介紹了Java 重命名 Excel 工作表并設(shè)置工作表標(biāo)簽顏色的示例代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java中的set集合是什么意思

    Java中的set集合是什么意思

    這篇文章主要介紹了Java中的set集合是什么意思,詳細(xì)地講解一下Collection集合中的另外一個(gè)分支——Set系列集合,需要的朋友可以參考下
    2022-05-05
  • 深入理解Spring Boot屬性配置文件

    深入理解Spring Boot屬性配置文件

    這篇文章主要給大家深入的介紹了關(guān)于Spring Boot屬性配置文件的相關(guān)資料,文中介紹的很詳細(xì),相信對大家具有一定的參考借鑒價(jià)值,需要的朋友們下面來一起看看吧。
    2017-02-02
  • MyBatis?Xml映射文件之字符串替換方式

    MyBatis?Xml映射文件之字符串替換方式

    這篇文章主要介紹了MyBatis?Xml映射文件之字符串替換方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評(píng)論

陇南市| 紫阳县| 基隆市| 万安县| 凤庆县| 温州市| 山东| 寿阳县| 贞丰县| 松潘县| 乐清市| 安平县| 永城市| 合阳县| 普兰店市| 凤山市| 青铜峡市| 聊城市| 鹤岗市| 万荣县| 绥江县| 泰安市| 广宗县| 蓬安县| 桃江县| 肥乡县| 康马县| 乌拉特前旗| 临朐县| 西昌市| 永清县| 小金县| 武冈市| 合江县| 木兰县| 蚌埠市| 鸡西市| 彩票| 双流县| 沂南县| 唐河县|