AES加密,前端加密,后端解密
概述:
在实现基本http 认证的场景下,我们希望认证信息最好不要以明文的形式进行传递,那么这里可以采用 AES 的加解密的方案来实现。
场景:
前后端使用 Baisc 认证,认证信息使用AES进行加密,添加时间戳来防止重复,在一定程度上增加访问的安全性。
注意事项:
* 前后端需要使用相同的AES-256-CBC算法和PKCS5Padding填充
* 前后端使用相同的128位(16字节)IV向量,与128位(16字节)或倍数的秘钥
前端加密:
const crypto = require('crypto');class AesUtil {constructor(key, iv) {this.key = Buffer.from(key, 'utf8');this.iv = Buffer.from(iv, 'utf8');this.algorithm = 'aes-256-cbc';}/*** AES加密* @param {string} text - 要加密的文本* @returns {string} 加密后的Base64字符串*/encrypt(text) {try {const cipher = crypto.createCipheriv(this.algorithm, this.key, this.iv);let encrypted = cipher.update(text, 'utf8', 'base64');encrypted += cipher.final('base64');return encrypted;} catch (error) {throw new Error('AES加密失败: ' + error.message);}}/*** 生成带时间戳的认证信息* @param {string} username - 用户名* @param {string} password - 密码* @returns {Object} 认证头对象*/generateAuthData(username, password) {const timestamp = Date.now();const credentials = `${username}:${password}:${timestamp}`;const encryptedData = this.encrypt(credentials);return {encryptedData: encryptedData,timestamp: timestamp,authHeader: `Basic ${Buffer.from(encryptedData).toString('base64')}`,headers: {'Authorization': `Basic ${Buffer.from(encryptedData).toString('base64')}`,'X-Timestamp': timestamp.toString(),'X-Encrypted': 'true','Content-Type': 'application/json'}};}
}const aesUtil = new AesUtil('12345678901234561234567890123456', '1234567890123456');
console.log(aesUtil.generateAuthData('admin', '12345678@'))运行后得到如下打印:
{encryptedData: 'Hrx1LVwnBFMfvGgv64rcPpXIMH9pNX4MWfkS+sPXb3Q=',timestamp: 1763183507151,authHeader: 'Basic SHJ4MUxWd25CRk1mdkdndjY0cmNQcFhJTUg5cE5YNE1XZmtTK3NQWGIzUT0=',headers: {Authorization: 'Basic SHJ4MUxWd25CRk1mdkdndjY0cmNQcFhJTUg5cE5YNE1XZmtTK3NQWGIzUT0=','X-Timestamp': '1763183507151','X-Encrypted': 'true','Content-Type': 'application/json'}
}
后端解密:
public class AesUtil {private static final String ALGORITHM = "AES";private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";private static final String secretKey = "12345678901234561234567890123456";private static final String iv = "1234567890123456";/*** AES解密** @param encryptedText 加密文本* @return 解密后的字符串*/public static String decrypt(String encryptedText) {try {SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);byte[] decodedBytes = Base64.getDecoder().decode(encryptedText);byte[] decryptedBytes = cipher.doFinal(decodedBytes);return new String(decryptedBytes, StandardCharsets.UTF_8);} catch (Exception e) {throw new RuntimeException("AES解密失败", e);}}public static void main(String[] args) {String encryptedData = "Hrx1LVwnBFMfvGgv64rcPpXIMH9pNX4MWfkS+sPXb3Q=";String decrypt = AesUtil.decrypt(encryptedData);System.out.println(decrypt);}
}运行后得到如下结果:
admin:12345678@:1763183507151
该功能经过验证,可以接口具体的业务场景,进行改造适配。
