基于Angular实现加密文件上传Azure Container及端侧解密的技术咨询
Angular 端 Azure Blob 加密图片上传与解密查看实现方案
基于你已有的Azure Blob基础上传、拉取能力,以下采用客户端AES对称加密方案实现需求,无需修改Azure服务端配置:
1. 加密图片上传至Azure Container
实现步骤:
- 安装加密依赖:
npm install crypto-js @types/crypto-js - 封装AES加密工具方法,这里采用安全性更高的GCM模式,支持数据完整性校验:
import * as CryptoJS from 'crypto-js'; // 生产环境密钥请从后端鉴权接口拉取,禁止硬编码在前端代码中 const AES_SECRET_KEY = '替换为你的32位长度AES256密钥'; /** * 加密文件为Blob * @param file 原始上传图片文件 * @returns 加密后的Blob对象 */ const encryptImageFile = (file: File): Promise<Blob> => { return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = (loadEvent) => { try { const fileContent = CryptoJS.lib.WordArray.create(loadEvent.target?.result as ArrayBuffer); // GCM模式推荐使用12字节随机IV const iv = CryptoJS.lib.WordArray.random(12); const encryptResult = CryptoJS.AES.encrypt(fileContent, AES_SECRET_KEY, { iv: iv, mode: CryptoJS.mode.GCM, padding: CryptoJS.pad.NoPadding }); // 将IV拼接在加密数据开头,解密时需要读取 const combineData = iv.concat(encryptResult.ciphertext); const encryptBlob = new Blob( [combineData.toString(CryptoJS.enc.Latin1)], { type: file.type } ); resolve(encryptBlob); } catch (err) { reject(err); } }; fileReader.onerror = () => reject(fileReader.error); fileReader.readAsArrayBuffer(file); }); };
- 改造原有上传逻辑:用户选择上传图片后,先调用
encryptImageFile得到加密Blob,将该Blob代替原始文件传入你现有的Azure上传方法即可,上传时建议保留原始文件的Content-Type元数据,方便后续解密渲染。
2. 拉取加密图片解密后查看
实现步骤:
- 封装对应的AES解密工具方法:
/** * 解密加密Blob为原始图片Blob * @param encryptBlob 从Azure拉取的加密图片Blob * @returns 解密后的原始图片Blob */ const decryptImageBlob = (encryptBlob: Blob): Promise<Blob> => { return new Promise((resolve, reject) => { const blobReader = new FileReader(); blobReader.onload = (loadEvent) => { try { const arrayBuffer = loadEvent.target?.result as ArrayBuffer; // 读取前12字节为加密时的IV const iv = CryptoJS.lib.WordArray.create(arrayBuffer.slice(0, 12)); // 剩余部分为加密数据 const cipherText = CryptoJS.lib.WordArray.create(arrayBuffer.slice(12)); const decryptResult = CryptoJS.AES.decrypt( { ciphertext: cipherText } as CryptoJS.lib.CipherParams, AES_SECRET_KEY, { iv: iv, mode: CryptoJS.mode.GCM, padding: CryptoJS.pad.NoPadding } ); // 解密结果转Blob const decryptedUint8 = new Uint8Array(decryptResult.words.length * 4); for (let i = 0; i < decryptResult.words.length; i++) { decryptedUint8[i * 4] = (decryptResult.words[i] >> 24) & 0xff; decryptedUint8[i * 4 + 1] = (decryptResult.words[i] >> 16) & 0xff; decryptedUint8[i * 4 + 2] = (decryptResult.words[i] >> 8) & 0xff; decryptedUint8[i * 4 + 3] = decryptResult.words[i] & 0xff; } resolve(new Blob([decryptedUint8], { type: encryptBlob.type })); } catch (err) { reject(err); } }; blobReader.onerror = () => reject(blobReader.error); blobReader.readAsArrayBuffer(encryptBlob); }); };
- 改造原有拉取查看逻辑:从Azure拉取到加密图片Blob后,调用
decryptImageBlob得到解密后的原始Blob,通过URL.createObjectURL(decryptBlob)生成临时访问链接,赋值给img标签的src属性即可正常显示图片。 - 优化提示:图片渲染完成后调用
URL.revokeObjectURL(临时链接)释放内存,避免内存泄漏。
安全注意:前端硬编码密钥存在泄露风险,生产环境建议将密钥存储在后端服务,用户完成身份鉴权后再返回对应密钥,也可配合Azure Key Vault托管密钥实现更高安全等级的加密逻辑。
内容的提问来源于stack exchange,提问作者GMAC
相关产品推荐
相关产品推荐

