前端参数传至后端,需要加密参数,以防止被爆破和信息泄漏。又因为是暴露给外部使用的接口,无法使用oath2等内部权限
前端使用vue开发。后端主要使用java开发。加密方案使用AES算法。 base64。
首先我们使用 crypto-js加密类库
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();
}
}
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));
commons-net
commons-net
3.0.1
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 @不止鱼
*
* 因为某些国家的进口管制限制,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=="));
}
}
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的博客 - CSDN博客
https://blog.csdn.net/qq_15070281/article/details/83652159