前后端通信进行AES加密(Vue - Java)

一. 前端工作

1. 安装crypto-js

安装命令:npm install crypto-js

2. js编写

import CryptoJS from "crypto-js";

const CRYPTOJSKEY= "abcdefgabcdefg12";
// 加密
const encrypt = (plaintText)=> {
    var plaintText = plaintText;
    var options = {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    };
    var key = CryptoJS.enc.Utf8.parse(CRYPTOJSKEY);
    var encryptedData = CryptoJS.AES.encrypt(plaintText, key, options);
    var encryptedBase64Str = encryptedData.toString();
    // encryptedBase64Str = encryptedBase64Str;
    return encryptedBase64Str;
};
//解密
const decrypt = (encryptedBase64Str) => {
    var vals = encryptedBase64Str;
    var options = {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    };
    var key = CryptoJS.enc.Utf8.parse(CRYPTOJSKEY);
    var decryptedData = CryptoJS.AES.decrypt(vals, key, options);
    var decryptedStr = CryptoJS.enc.Utf8.stringify(decryptedData);
    return decryptedStr
};
export default{
    encrypt,
    decrypt,
}

二. 后端工作

1. 编写加密工具类

package com.visionvera.common.utils;

import java.math.BigInteger;

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

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

import sun.misc.BASE64Decoder;

/**
 * AES的加密和解密
 *
 * @author jlm
 */
public class AESUtil {

    //密钥 (需要前端和后端保持一致)
    private static String KEY = "abcdefgabcdefg12";
    //算法
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";

    /**
     * aes解密
     *
     * @param encrypt 内容
     * @return
     * @throws Exception
     */
    public static String aesDecrypt(String encrypt) {
        try {
            return aesDecrypt(encrypt, KEY);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * aes加密
     *
     * @param content
     * @return
     * @throws Exception
     */
    public static String aesEncrypt(String content) {
        try {
            return aesEncrypt(content, KEY);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 将byte[]转为各种进制的字符串
     *
     * @param bytes byte[]
     * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
     * @return 转换后的字符串
     */
    public static String binary(byte[] bytes, int radix) {
        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
    }

    /**
     * base 64 encode
     *
     * @param bytes 待编码的byte[]
     * @return 编码后的base 64 code
     */
    public static String base64Encode(byte[] bytes) {
        return Base64.encodeBase64String(bytes);
    }

    /**
     * base 64 decode
     *
     * @param base64Code 待解码的base 64 code
     * @return 解码后的byte[]
     * @throws Exception
     */
    public static byte[] base64Decode(String base64Code) throws Exception {
        return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
    }


    /**
     * AES加密
     *
     * @param content    待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的byte[]
     * @throws Exception
     */
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));

        return cipher.doFinal(content.getBytes("utf-8"));
    }


    /**
     * AES加密为base 64 code
     *
     * @param content    待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的base 64 code
     * @throws Exception
     */
    public static String aesEncrypt(String content, String encryptKey) throws Exception {
        return base64Encode(aesEncryptToBytes(content, encryptKey));
    }

    /**
     * AES解密
     *
     * @param encryptBytes 待解密的byte[]
     * @param decryptKey   解密密钥
     * @return 解密后的String
     * @throws Exception
     */
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
        byte[] decryptBytes = cipher.doFinal(encryptBytes);
        return new String(decryptBytes);
    }


    /**
     * 将base 64 code AES解密
     *
     * @param encryptStr 待解密的base 64 code
     * @param decryptKey 解密密钥
     * @return 解密后的string
     * @throws Exception
     */
    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
        return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
    }

    /**
     * 测试
     */
    public static void main(String[] args) throws Exception {
        String content = "123";
        System.out.println("加密前:" + content);
        System.out.println("加密密钥和解密密钥:" + KEY);
        String encrypt = aesEncrypt(content, KEY);
        System.out.println("加密后:" + encrypt);
        String decrypt = aesDecrypt("Sy93OjPDF5vwNrkTfL9AyA==", KEY);
        System.out.println("解密后:" + decrypt);
    }

注意:秘钥需前后端保持一致,以上代码亲测可用

 

先运行safechat包里的greetigserver.class,之后运行greetingclient.class即可。 如遇报错,请参考:https://blog.youkuaiyun.com/fengzun_yi/article/details/104497160 实现过程: 1. 采用TCP通信协议完成接收者发送者双方的消息传递。 2. 利用Diffie-Hellman密钥交换协议生成对称加密通信通信密钥。 3. 为防止中间人攻击,采用RSA非对称加密算法协助DH算法完成密钥交换。具体过程如下: a. 接收者与发送者双方各自利用RSA算法生成自己的公私钥,并生成数字证书,并在一个CA进行认证。 b. 在DH密钥交换阶段,A生成A的DH协商密钥用于发送给B,该密钥与接收方私钥生成最终通信密钥。发送DH密钥时,A先用自己的私钥加密DH协商密钥,再去CA获得一个真实的B的公钥,用B的公钥对加密过的协商密钥再做一次加密,发送给B。(因为是用B的公钥加密过,只有B有B的私钥,所以接收信息只有B自己可以解密查看,又因为是用A的私钥加密过的,只有A有A的私钥,所以只有用A的公钥可以进行解密,所以可以保证协商密钥确实是A发送过来的,而且发送的信息也无法被中间人解密。)B收到信息之后,先用自己的私钥解密,然后去CA获得A的公钥再对消息解密一次,获得A的DH密钥。B发给A的过程同上。 c. 之后双方执行DH生成本地密钥的过程。A利用B发送过来的密钥和A的DH私钥生成通信密钥。B利用A发送过来的密钥和B的DH私钥生成通信密钥。根据DH原理,两者生成的通信密钥是相同的。 4. 利用上一步生成的通信密钥,采用AES对称加密算法进行加密通信。 为了方便起见,并没用对A和B双方进行颁发证书的操作,A的公钥默认B已经从CA获得,B的公钥默认A已经从CA获得。并且采用java控制台交互,仅仅为演示原理及简单效果。
<think>好的,我现在需要帮用户找到一个适合前后端加密传输的安全方案。用户提到了加密方式、数据保护、HTTPS、AES、JWT这些关键词。首先,我得回忆一下相关的知识,结合提供的引用内容来构建一个合理的方案。 首先,用户引用的内容提到了前后端联合加密方案,特别是传统上明文传输密码的问题,以及使用Bcrypt、JWT等技术的应用。引用[1]指出传统方案中密码是明文传输,后端加密存储,而其他数据不加密。这可能存在中间人攻击的风险,所以需要更全面的加密策略。 接下来,引用[2]提到设计了一个前后端数据加密传输方案,目的是防止黑客轻易获取传输数据。这可能涉及在传输层和应用层的双重加密。结合用户提到的HTTPS,这应该是基础,因为HTTPS提供了传输层的加密,防止数据在传输过程中被窃听或篡改。 然后,用户提到的AES和JWT。AES是对称加密,适合加密大量数据,而JWT用于令牌认证,确保请求的合法性。引用[3]和[4]都提到了JWT的使用,包括拦截器和权限控制。这说明在认证方面,JWT是一个重要组成部分,但需要安全地存储和传输,比如放在HTTP Only的Cookie中,防止XSS攻击。 现在需要将这些元素整合成一个方案。首先,必须使用HTTPS作为基础,确保传输层安全。其次,对于敏感数据,比如密码,前端应该先进行哈希处理,可能结合盐值,避免明文传输。不过引用[1]提到传统方案是发送明文密码,但用户需要更安全的方案,所以可能需要前端加密后再传输,例如使用AES加密整个请求体,后端用AES解密。不过要注意密钥管理的问题,可能需要动态生成密钥或者使用非对称加密交换密钥。 另外,JWT的使用需要注意其安全性,比如签名算法、有效期控制,避免令牌被盗用。引用[4]提到AES加密和JWT整合,可能是在生成JWT时对内容进行加密,或者传输JWT时使用安全的方式。 可能的问题点包括:如何安全地交换AES密钥,防止中间人攻击;如何保证前端加密逻辑的安全性,避免泄露密钥;如何处理加密后的数据传输和存储等。需要综合这些因素,给出分层的安全措施。 最后,要确保方案符合最佳实践,比如使用强加密算法,定期轮换密钥,结合访问控制等。同时,生成相关问题,帮助用户进一步理解方案的细节和优化方向。</think>针对前后端加密传输的安全需求,建议采用分层加密方案,结合HTTPS、AES和JWT技术,以下是分步实施方案: ### 一、核心分层加密架构 1. **传输层加密**(基础防护) 必须强制使用HTTPS协议,通过TLS/SSL加密整个通信链路,防止中间人攻击和数据窃听。这是所有安全措施的基础[^2][^4]。 2. **应用层加密**(数据保护) - **敏感数据预处理** 密码等核心敏感字段在前端使用Bcrypt或PBKDF2算法进行哈希处理,避免明文传输[^1]。 - **AES加密传输体** 对请求体/响应体数据采用AES-GCM模式加密,示例流程: ```javascript // 前端加密(需预协商密钥或动态生成) const encryptedData = CryptoJS.AES.encrypt( JSON.stringify({user: 'name', pwd: 'hashed_value'}), 'base64_encoded_key' ).toString(); ``` ```java // 后端解密(Spring示例) Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new GCMParameterSpec(128, iv)); byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedStr)); ``` 3. **身份认证层**(JWT增强) 采用JWT作为无状态令牌时需增加以下防护: - 使用**HS512**或**RS512**强签名算法 - 设置短期有效期(如15分钟) - 通过HTTP Only + Secure标记存储Cookie - 敏感声明(如用户ID)可进行二次AES加密[^3][^4] ### 二、密钥安全管理方案 $$k_{dynamic} = HMAC(k_{master}, timestamp) \oplus nonce$$ 采用动态密钥派生机制,主密钥$k_{master}$仅在后端HSM中存储,每次会话通过时间戳和随机数生成临时密钥$k_{dynamic}$,前端通过RSA加密交换该密钥。 ### 三、防御纵深设计 | 攻击类型 | 防御措施 | |----------------|-----------------------------------| | 重放攻击 | 请求时间戳校验 + 随机数缓存 | | 数据篡改 | HMAC签名验证 + TLS证书绑定 | | 密钥泄露 | 硬件安全模块(HSM) + 密钥轮换策略 | ### 四、实施示例代码 前端加密配置(Vue): ```javascript // AES密钥协商 async function initSession() { const { publicKey } = await fetch('/api/get-rsa-key'); const aesKey = crypto.randomBytes(32); const encryptedKey = rsaEncrypt(aesKey, publicKey); localStorage.setItem('sessionKey', encryptedKey); } ``` 后端解密拦截器(Spring Boot): ```java @Bean public FilterRegistrationBean<AesDecryptFilter> aesFilter() { FilterRegistrationBean<AesDecryptFilter> reg = new FilterRegistrationBean<>(); reg.setFilter(new AesDecryptFilter()); reg.addUrlPatterns("/api/secure/*"); return reg; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值