【分布式安全】【加密】前端vue和后端java使用AES加密参数互相验证请求

博客针对前端参数传至后端需加密以防爆破和信息泄漏的需求,给出解决方案。前端用Vue开发,使用crypto-js加密类库;后端用Java开发,引入base64依赖。同时强调前后端相互校验,需有共同的key配置、算法/模式/补码方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求背景

前端参数传至后端,需要加密参数,以防止被爆破和信息泄漏。又因为是暴露给外部使用的接口,无法使用oath2等内部权限

技术栈

前端使用vue开发。后端主要使用java开发。加密方案使用AES算法。 base64。

解决方案

前端vue解决方案

首先我们使用 crypto-js加密类库

1)安装

cnpm install crypto-js --save

此外使用淘宝的cnpm, 下载速度快。若没有安装淘宝此包。直接使用npm也是可以的
2) 写一个通用工具js

/**
 * AES工具类
 */
import CryptoJS from 'crypto-js'
const aeskey = "crm25sqdc58start";

const KEY = CryptoJS.enc.Utf8.parse("zhelixie16weimim"); //""中与后台一样  密码
const IV = CryptoJS.enc.Utf8.parse("zhelixie16weimim"); //""中与后台一样
export default { //加密
  encrypt(word) {
    let key = KEY
    let iv = IV
    let srcs = CryptoJS.enc.Utf8.parse(word);
    var encrypted = CryptoJS.AES.encrypt(srcs, key, {
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.ZeroPadding
    });
    // console.log("-=-=-=-", encrypted.ciphertext)
    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
  },
  //解密
  decrypt(word) {
    let key = KEY
    let iv = IV
    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();
  }

}

 3)调用

import AesUtil from "@/utils/aes-util";

...

let encryLink = AesUtil.encrypt(this.userInfo.userId);

let deencryLink = AesUtil.decrypt(encryLink);

如果是放在url里的参数,还需要对整个uri encode或对参数encode,不然如果里面有加号等特殊符号,后端收到会出现问题。

this.link =
        this.link +
        "?param=" +
        encodeURIComponent(AesUtil.encrypt(this.userInfo.userId));

 后端Java解决方案

1)引入base64依赖

<dependency>
			<groupId>commons-net</groupId>
			<artifactId>commons-net</artifactId>
			<version>3.0.1</version>
		</dependency>

2)写一个util类

 package com.bj58.crm.sqdc.util;  
  
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.net.util.Base64;  
  
  
/** 
 * AES工具类 
 * @author paymoon.com @不止鱼
 * <pre> 
 *   因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件。 
 *   替换的文件:%JDK_HOME%\jre\lib\security\local_policy.jar 
 * 参考: http://czj4451.iteye.com/blog/1986483 
 */  
public class AESUtil {  
    // 密钥  
    public static String key = "zhelixie16weimim";  
    private static String charset = "utf-8";  
    // 偏移量  
    private static int offset = 16;  
    private static String transformation = "AES/CBC/NoPadding";  
    private static String algorithm = "AES";  
  
    /** 
     * 加密 
     *  
     * @param content 
     * @return 
     */  
    public static String encrypt(String content) {  
        try {
			return encrypt(content, key);
		} catch (Exception e) {
		}
		return null;  
    }  
  
    /** 
     * 解密 
     *  
     * @param content 
     * @return 
     */  
    public static String decrypt(String content) {  
        return decrypt(content, key);  
    }  
  
    /** 
     * 加密 
     *  
     * @param content 
     *            需要加密的内容 
     * @param key 
     *            加密密码 
     * @return 
     */  
//    public static String encrypt(String content, String key) {  
//        try {  
//            SecretKeySpec skey = new SecretKeySpec(key.getBytes(Charset.forName("UTF-8")), algorithm);  
//            IvParameterSpec iv = new IvParameterSpec(key.getBytes(Charset.forName("UTF-8")), 0, offset);  
//            Cipher cipher = Cipher.getInstance(transformation);  
//            byte[] byteContent = content.getBytes(charset);  
//            cipher.init(Cipher.ENCRYPT_MODE, skey, iv);// 初始化  
//            byte[] result = cipher.doFinal(byteContent);  
//            return new Base64().encodeToString(result); // 加密  
//        } catch (Exception e) {  
//        }  
//        return null;  
//    }  
    public static String encrypt(String data, String key) throws Exception {
        try {

            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");//"算法/模式/补码方式"NoPadding PkcsPadding
            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(key.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;
        }
    }

    /** 
     * AES(256)解密 
     *  
     * @param content 
     *            待解密内容 
     * @param key 
     *            解密密钥 
     * @return 解密之后 
     * @throws Exception 
     */  
    public static String decrypt(String content, String key) {  
        try {  
  
            SecretKeySpec skey = new SecretKeySpec(key.getBytes(), algorithm);  
            IvParameterSpec iv = new IvParameterSpec(key.getBytes(), 0, offset);  
            Cipher cipher = Cipher.getInstance(transformation);  
            cipher.init(Cipher.DECRYPT_MODE, skey, iv);// 初始化  
            byte[] result = cipher.doFinal(new Base64().decode(content));  
            return new String(result); // 解密  
        } catch (Exception e) {  
        }  
        return null;  
    }  
  
    public static void main(String[] args) throws Exception {  
        String s = "65de2594-9ace-e211-915e-00155d607702";  
        // 加密  
        System.out.println("加密前:" + s);  
        String encryptResultStr = encrypt(s);  
        System.out.println("加密后:" + encryptResultStr);  
        // 解密  
        System.out.println("解密后:" + decrypt("CehzNznR6gQfgwahwUuoog=="));  
    }  
}  

3)方法调用直接参数main即可

加密注意的点

1、前后端相互校验,不同于单后端或前端加密。两端需要有共同的key配置。算法/模式/补码方式。

2、后端java加密的算法/模式/补码方式配置是 AES/CBC/NoPadding,偏移量使用的是key。则前端vue中,也要使用相同的偏移,以及模式CBC,补码使用CryptoJS.pad.ZeroPadding。

参考

vue 方案https://chris-wei.github.io/2018/04/13/Crypto-js/

java和vue使用AES加密验证前端请求 - qq_15070281的博客 - 优快云博客
https://blog.youkuaiyun.com/qq_15070281/article/details/83652159

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不止鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值