前後端分離 Vue 和 API 接口數據加密(AES)

前言

就前後端分離的開發方式而言,我們以接口爲標準來進行推動,定義好接口,各自開發自己的功能,最後進行聯調整合。前後端的傳輸通過HTTP進行傳輸,也帶來了一些安全問題,如果抓包、模擬請求、洪水攻擊、參數劫持、網絡爬蟲等都能夠獲取請求的數據包。那麼如何對數據進行保護呢?

可以提升網絡安全的方式

  • 採用HTTPS協議

  • 密鑰存儲到服務端而非客戶端,客戶端應從服務端動態獲取密鑰

  • 請求隱私接口,利用token機制校驗其合法性

  • 對請求參數進行合法性校驗

  • 對請求參數進行簽名認證,防止參數被篡改

  • 對輸入輸出參數進行加密,客戶端加密輸入參數,服務端加密輸出參數

HTTP VS HTTPS

普通的HTTP協議是以明文形式進行傳輸,不提供任何方式的數據加密,很容易解讀傳輸報文。而HTTPS協議在HTTP基礎上加入了SSL層,而SSL層通過證書來驗證服務器的身份,併爲瀏覽器和服務器之間的通信加密,保護了傳輸過程中的數據安全。

Aes數據加密實現方式

實現步驟:前端對數據進行加密,API對收到的數據進行解密。操作後,將數據在次加密並返回給前端,前端使用解密後的數據。

說明:Aes 中加密解密有多種模式,本文以base64爲例。

vue 中封裝的加密解密文件 ase.js

/***
 * aes Base64 方式加密解密
 */
const CryptoJS = require('crypto-js');  //引用AES源碼js    
const key = CryptoJS.enc.Utf8.parse("FFff123456.!-12ss");  //十六位十六進制數作爲密鑰
const iv = CryptoJS.enc.Utf8.parse('FFff123456.!-12ss');   //十六位十六進制數作爲密鑰偏移量
    
//解密方法
function Decrypt(word) {
  let base64 = CryptoJS.enc.Base64.parse(word);
  let src = CryptoJS.enc.Base64.stringify(base64);
  var decrypt = CryptoJS.AES.decrypt(src, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding});
  var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
  return decryptedStr.toString();
}

//加密方法
function Encrypt(word) {
    let srcs = CryptoJS.enc.Utf8.parse(word);
    var encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding});
    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}
    
export default {
    Decrypt ,
    Encrypt
}

API 中封裝的加密解密文件 Aes.java

package com.platform.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

/***
 * Aes Base64 加密和解密
 * @author Zyh
 *
 */
public class Aes {

	//密鑰 (需要前端和後端保持一致)
    private static final String KEY = "FFff123456.!-12ss";
    private static final String IV = "FFff123456.!-12ss";
    
    /**
     * 加密方法
     * @param data  要加密的數據
     * @param key 加密key
     * @param iv 加密iv
     * @return 加密的結果
     * @throws Exception
     */
    public static String encrypt(String data, String key, String iv) throws Exception {
        try {
 
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new Base64().encodeToString(encrypted);
 
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 解密方法
     * @param data 要解密的數據
     * @param key  解密key
     * @param iv 解密iv
     * @return 解密的結果
     * @throws Exception
     */
    public static String desEncrypt(String data, String key, String iv) throws Exception {
        try {
            byte[] encrypted1 = new Base64().decode(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 使用默認的key和iv加密
     * @param data
     * @return
     * @throws Exception
     */
    public static String encrypt(String data) throws Exception {
        return encrypt(data, KEY, IV);
    }
     
    /**
     * 使用默認的key和iv解密
     * @param data
     * @return
     * @throws Exception
     */
    public static String desEncrypt(String data) throws Exception {
        return desEncrypt(data, KEY, IV);
    }
   
}

至此,就可以進行前後端數據加密傳輸,這也僅僅是其中的一種解決方案,關於加解密的方法還有很多,感興趣的小夥伴們可以繼續做一些深入的研究哈~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章