ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vue 3前端加密实战:六种加密方式原理与工程落地

Vue 3前端加密实战:六种加密方式原理与工程落地 前端做数据加密这件事很多同学一开始都是懵的明明数据最终要发给后端后端拿到也要解密那前端加密的意义到底在哪这问题的答案其实就俩字——降低风险。Vue项目里不管是登录密码、用户手机号还是接口请求参数直接在控制台或抓包工具里以明文方式裸露等于把家门钥匙挂在门口。加密不是为了防住国家级黑客而是为了防住那些顺手牵羊的低门槛攻击以及满足等保、合规审计对敏感数据传输的基本要求。这篇文章我会基于Vue 3 Vite的技术栈把六种最常见的数据加密方式从原理到落地全部捋一遍。每种都会给出能直接复制改的业务代码还会带着讲清楚它们的适用场景、局限性以及在真实项目里组合使用的思路。适合已经能熟练写Vue组件、想往工程化和安全方向进阶的同学参考。1. 内容整体设计与思路拆解1.1 先搞明白前端加密到底在防什么很多人一听前端加密就嗤之以鼻觉得前端代码都暴露在浏览器里加密等于自欺欺人。这种说法有一定道理但只对了一半。前端加密的定位从来不是绝对安全而是增加攻击成本。举个很典型的场景你的登录接口是POST请求参数是用户名和密码。如果不做任何处理用户在浏览器里输入密码点击登录F12打开Network面板密码清清楚楚躺在Payload里。这时候任何一个能打开浏览器开发者工具的人都能直接看到用户的密码明文。更糟糕的是很多人的密码是跨平台复用的拿到一个明文密码等于拿到了他半个数字身份。前端加密解决的核心问题有三类传输层之外的裸奔问题HTTPS能保证数据在传输过程中不被窃听但在浏览器到应用层这一端数据是明文存在于内存和网络面板中的。加密可以让这些环节暴露出来的不再是原始密码。接口被恶意刷的问题请求参数加上签名机制之后攻击者即使抓到了请求修改任何参数都会导致签名校验失败能挡掉大量低水平的自动化攻击脚本。合规层面的基本要求现在很多等保测评、隐私合规检查都会明确要求敏感信息在传输前进行加密处理。前端加密是满足这些审查的红线动作之一。所以前端加密解决方案的设计思路应该是让攻击者拿到数据之后要付出足够高的代价才能还原出真正有价值的信息。这也是为什么我们要用多种加密方式组合而不是只上一种。1.2 六种加密方式的分类与选型逻辑先给这六种方式归个类方便理解它们之间的区别类型代表方式核心特征主要用途编码类Base64可逆但非加密只是一种数据表示形式传输二进制数据、URL参数处理哈希摘要MD5 / SHA-256不可逆相同输入必得相同输出校验数据完整性、防篡改对称加密AES加解密用同一个密钥速度快大数据量内容加密非对称加密RSA公钥加密、私钥解密速度慢敏感密钥传输、小数据量加密混合方案AES RSA兼顾性能与安全接口签名、登录密码传输选型的逻辑其实很直接先想清楚你要保护什么再决定用哪种方式。如果只是让密码不在Network面板里裸奔MD5加盐就够了如果需要完整加密一段JSON数据体AES是主流选择如果还要考虑密钥本身的安全传递那就得引入RSA做混合加密。另外需要强调的是这里说加密其实是广义的从严格意义来讲Base64和MD5都不算加密算法——前者是编码后者是摘要。但在前端业务里它们是被当作加密手段来用的所以我把它们归到这篇文章里统一讲解同时把各自的真实定位说清楚。2. 六种常用加密方式逐个击破2.1 Base64编码最基础的工具但别把它当加密用Base64在Vue项目里的出场频率很高比如把文件转成Base64预览、把二进制数据塞到JSON里传、处理URL参数编码。它的工作原理是把3个字节24位的数据转换成4个可打印字符每个字符占6位。用法很简单浏览器原生就支持// 编码 const encoded btoa(hello world) console.log(encoded) // aGVsbG8gd29ybGQ // 解码 const decoded atob(encoded) console.log(decoded) // hello world但在Vue项目里直接使用btoa有一个很恶心的坑它对中文支持极差遇到非Latin1字符直接抛异常。处理中文内容时要先用encodeURIComponent转一下// 处理中文的兼容写法 export function base64Encode(str: string): string { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, p1) String.fromCharCode(parseInt(p1, 16)))) } export function base64Decode(str: string): string { return decodeURIComponent(atob(str).split().map((c) % c.charCodeAt(0).toString(16).padStart(2, 0)).join()) }我在实际项目中一般用crypto-js的enc.Base64来处理它对Unicode的支持更省心import CryptoJS from crypto-js const encoded CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(你好Vue)) const decoded CryptoJS.enc.Base64.parse(encoded).toString(CryptoJS.enc.Utf8)重点提醒Base64相当于是把数据换了一层马甲任何拿到编码结果的人都能轻易解码还原。它适合用来做数据传输格式转换但绝不适合用来保护密码这类敏感信息。文章标题里把它列成加密方式之一是因为业务中它经常作为加密链路的第一个环节出现但要清醒认识到它的短板。2.2 MD5加盐不可逆的数字指纹防篡改利器MD5是一种哈希算法输入任意长度的数据输出固定128位32个十六进制字符的摘要。它的关键特性是单向不可逆也就是你没法从摘要反推出原始内容。但它有个明显的缺陷对相同输入永远生成相同摘要。这就意味着攻击者可以提前准备好彩虹表——把常见密码的MD5值都算出来——然后一比对明文密码就直接暴露了。所以MD5的正确用法是加盐salt就是在原文后面拼接一段只有前后端约定的随机字符串再做哈希。npm install crypto-js看一下Vue里的封装写法import CryptoJS from crypto-js // 加盐MD5 export function md5WithSalt(content: string, salt: string vue-advanced-2024) { return CryptoJS.MD5(content salt).toString() } // 使用示例登录时对密码做加盐MD5 const passwordHash md5WithSalt(loginForm.password) request.post(/api/login, { username: loginForm.username, password: passwordHash })不过我要泼一盆冷水MD5本身已经被证明存在碰撞风险业界不建议用于安全性要求高的场景。如果后端团队没有强制的MD5要求我更推荐直接用SHA-256替代MD5这也是为什么下一节要单独讲SHA系列的原因。MD5在Vue项目里还有个高频用途是生成缓存版本号——把JSON数据、文件内容做一个MD5摘要作为缓存Key的一部分内容变了摘要就变缓存自动失效这个场景下MD5依然很好用。2.3 SHA-256比MD5更稳的摘要算法SHA家族里SHA-256是现在应用最广泛的哈希算法之一输出256位摘要64个十六进制字符碰撞难度远高于MD5。SHA-256和MD5同属哈希算法但安全性等级不同在等保测评里SHA-256基本是被认可的基础算法。import CryptoJS from crypto-js // SHA-256 基础用法 export function sha256(content: string): string { return CryptoJS.SHA256(content).toString() } // 加盐版 export function sha256WithSalt(content: string, salt: string vue-salt-2024) { return CryptoJS.SHA256(content salt).toString() }实际操作中我会把SHA-256用在接口请求参数签名上。思路是把请求参数按key排序拼成字符串加盐再做SHA-256得到sign值放到请求头里。后端用同样的规则计算一遍比对两个sign是否一致如果不一致就拒绝请求。这样攻击者一旦篡改了参数sign就会对不上请求直接被拦截。// 请求签名示例 function generateSign(params: Recordstring, any, secretKey: string) { const sortedKeys Object.keys(params).sort() const rawStr sortedKeys.map((key) ${key}${params[key]}).join() return sha256WithSalt(rawStr, secretKey) } // 在请求拦截器中使用 service.interceptors.request.use((config) { const params config.params || {} config.headers[X-Sign] generateSign(params, my-secret-key) return config })这里有个容易踩坑的点签名用的参数串必须和后端约定的完全一致。比如参数值是否需要URL解码、空值怎么处理、嵌套对象怎么序列化这些细节如果不统一前后端算出来的sign永远对不上排查起来非常痛苦。2.4 AES对称加密大数据量加密的主力方案AES是当前最主流的对称加密算法密钥长度支持128位、192位、256位。所谓对称加密就是加密和解密使用的是同一个密钥。它的优点是性能极好加密几KB、几MB的数据几乎没有明显延迟适合加密完整的请求体或响应体。在Vue项目里最常用的是crypto-js提供的AES实现。需要特别注意的是AES有多种工作模式、填充方式和偏移量IV设置前后端必须保持完全一致才能正确解密。import CryptoJS from crypto-js // 定义一个统一的加解密工具 const AES_KEY CryptoJS.enc.Utf8.parse(16位或32位密钥字符串) const AES_IV CryptoJS.enc.Utf8.parse(16位偏移量字符串) export function aesEncrypt(content: string): string { const encrypted CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(content), AES_KEY, { iv: AES_IV, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return encrypted.toString() } export function aesDecrypt(encryptedContent: string): string { const decrypted CryptoJS.AES.decrypt(encryptedContent, AES_KEY, { iv: AES_IV, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) return decrypted.toString(CryptoJS.enc.Utf8) }这段代码里有几个关键点必须清楚mode: CBC是最常用的分组模式每个明文块先与前一个密文块异或再加密安全性比ECB高但需要IV偏移量。padding: Pkcs7用于处理最后一个不满16字节的数据块填充到16字节的整数倍。Java后端的AES实现里常见的是PKCS5Padding实际上PKCS5和PKCS7在AES下行为一致可以互通。密钥和偏移量必须是WordArray类型直接传字符串会导致加解密结果不符合预期这是新手最容易踩的坑。AES的最大问题在于密钥怎么安全传递。前端代码是公开的密钥写死在JS里等于钥匙和锁放在一起。所以AES适合用在密钥可以通过后端接口动态下发的场景或者用于加密那些不涉及核心敏感数据的业务字段。2.5 RSA非对称加密解决密钥传递的信箱方案RSA是非对称加密里面涉及一对密钥公钥负责加密私钥负责解密。公钥可以公开分发任何人拿到公钥都能加密数据但只有持有私钥的后端才能解密。这就像街头邮筒——任何人都能往里投信但只有邮局工作人员拿着钥匙才能打开邮筒取信。在Vue项目里RSA最典型的应用场景就是登录密码加密前端用后端下发的公钥把密码加密后端用私钥解密。即使公钥被任何人看到也无法反推私钥密码就能在传输过程中得到保护。npm install jsencrypt用法如下import JSEncrypt from jsencrypt // 假设公钥由后端接口下发存在store里 const publicKey store.state.publicKey export function rsaEncrypt(content: string, key: string): string { const encryptor new JSEncrypt() encryptor.setPublicKey(key) return encryptor.encrypt(content) } // 使用示例 const encryptedPassword rsaEncrypt(loginForm.password, publicKey) request.post(/api/login, { username: loginForm.username, password: encryptedPassword })RSA的短板也很明显加密性能差、明文长度限制严格。1024位的RSA密钥最多只能加密117字节的明文2048位密钥最多只能加密245字节。所以RSA绝对不适用于加密整段JSON请求体只能加密密码、身份证号这类短小的敏感字段。这里还有一个工程细节加密结果在不同实现里的格式可能不同。jsencrypt输出的Base64密文Java后端的Cipher默认模式是RSA/ECB/PKCS1Padding是可以直接对接解密的。但如果你用的是其他库一定要确认填充模式否则会出现前端能加密、后端解不开的惨案。2.6 AESRSA混合加密进阶项目的标准答案既然AES速度快但密钥传递不安全RSA安全但性能差、长度受限那很自然的思路就是把两个结合起来用RSA加密AES的密钥用AES加密业务数据。这就是混合加密方案。整体流程是这样的前端随机生成一个AES密钥比如32位随机字符串。用这个AES密钥加密请求体数据。用后端下发的RSA公钥加密AES密钥本身。把加密后的数据体和加密后的AES密钥一起发给后端。后端先用RSA私钥解密出AES密钥再用AES密钥解密业务数据。Vue里的实现大致长这样import CryptoJS from crypto-js import JSEncrypt from jsencrypt export function hybridEncrypt(content: string, rsaPublicKey: string) { // 1. 随机生成AES密钥 const aesKey CryptoJS.lib.WordArray.random(16).toString() // 2. AES加密业务数据 const encryptedData CryptoJS.AES.encrypt(content, CryptoJS.enc.Utf8.parse(aesKey), { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, iv: CryptoJS.enc.Utf8.parse(0123456789abcdef) }).toString() // 3. RSA加密AES密钥 const encryptor new JSEncrypt() encryptor.setPublicKey(rsaPublicKey) const encryptedAesKey encryptor.encrypt(aesKey) return { encryptedData, encryptedAesKey } }这方案很优雅但也有需要权衡的地方每次请求都要做一次RSA加密虽然只加密很短的AES密钥但RSA计算本身还是比AES慢一个数量级。在登录、支付这类低频敏感接口上用这个方案完全没问题但如果是高频的业务查询接口性能损耗就值得评估了。我在真实项目里更常用的折中做法是AES密钥不每次随机生成而是定时轮换比如一小时换一次前端从后端接口获取AES密钥时走一次RSA加密后续请求直接用AES加密。这样既控制了RSA的计算次数又保证了密钥不会长期不变。3. 在Vue 3项目中完整落地登录加密与接口签名实战3.1 搭建依赖与工具模块先把需要用到的依赖装上npm install crypto-js jsencrypt然后创建一个src/utils/crypto.ts把所有加密方法统一封装起来。为什么单独建一个文件因为加密逻辑是横切关注点散落在各个组件里会导致维护成本极高集中封装后后续更换算法比如从MD5换到SHA-256只改一个文件。import CryptoJS from crypto-js import JSEncrypt from jsencrypt const SECRET_KEY your-aes-key-16bit const SECRET_IV your-aes-iv-16bit // Base64 export const base64Encode (str: string) CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str)) export const base64Decode (str: string) CryptoJS.enc.Base64.parse(str).toString(CryptoJS.enc.Utf8) // MD5 加盐 export const md5Encode (str: string, salt vue-advanced) CryptoJS.MD5(str salt).toString() // SHA-256 加盐 export const sha256Encode (str: string, salt vue-advanced) CryptoJS.SHA256(str salt).toString() // AES 对称加解密 export const aesEncrypt (str: string) { return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(str), CryptoJS.enc.Utf8.parse(SECRET_KEY), { iv: CryptoJS.enc.Utf8.parse(SECRET_IV), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString() } export const aesDecrypt (str: string) { return CryptoJS.AES.decrypt(str, CryptoJS.enc.Utf8.parse(SECRET_KEY), { iv: CryptoJS.enc.Utf8.parse(SECRET_IV), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8) } // RSA 非对称加密 export const rsaEncrypt (str: string, publicKey: string) { const encryptor new JSEncrypt() encryptor.setPublicKey(publicKey) return encryptor.encrypt(str) }封装好之后组件里只需要import { rsaEncrypt } from /utils/crypto不用关心底层是JSEncrypt还是crypto-js也不需要记住CBC、Pkcs7这些配置这才是工程化该有的样子。3.2 场景一登录密码加密落地方案登录是加密需求最刚的场景。我常用的方案是RSA加密密码因为密码是短字段长度限制完全够用。后端提供一个获取公钥的接口前端在登录页加载或用户点击登录时获取公钥script setup langts import { ref, onMounted } from vue import { rsaEncrypt } from /utils/crypto import { getPublicKeyApi, loginApi } from /api/auth import type { LoginForm } from /types/auth const loginForm refLoginForm({ username: , password: }) let publicKey onMounted(async () { // 从后端获取RSA公钥 const res await getPublicKeyApi() publicKey res.data.publicKey }) async function handleLogin() { if (!publicKey) { console.error(公钥尚未加载) return } // 密码先做RSA加密再提交 const encryptedPassword rsaEncrypt(loginForm.value.password, publicKey) await loginApi({ username: loginForm.value.username, password: encryptedPassword }) } /script这里有个容易被忽略的体验问题用户点了登录按钮但公钥还没从接口返回这时候点击登录就会失效。所以我会在获取公钥期间禁用登录按钮或者在公钥为空时给出明确提示而不是等着用户莫名其妙点了一次没反应。3.3 场景二请求参数全量签名更进阶的做法是给所有请求参数加签名防止参数在传输过程中被篡改。在axios拦截器里统一加签名不污染业务代码import axios from axios import { sha256Encode } from /utils/crypto const service axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 15000 }) const SIGN_SALT interface-signature-salt // 签名生成规则参数名按ASCII码排序拼成 keyvaluekeyvalue最后加盐做SHA-256 function generateSignature(params: Recordstring, any): string { const sortedKeys Object.keys(params).sort() const rawString sortedKeys .filter((key) params[key] ! undefined params[key] ! null) .map((key) ${key}${encodeURIComponent(params[key])}) .join() return sha256Encode(rawString, SIGN_SALT) } service.interceptors.request.use((config) { const method config.method?.toUpperCase() let params: Recordstring, any {} if (method GET) { params config.params || {} } else if (method POST || method PUT) { params config.data || {} } const timestamp Date.now().toString() const nonce Math.random().toString(36).substring(2, 15) const signParams { ...params, timestamp, nonce } const signature generateSignature(signParams) config.headers[X-Timestamp] timestamp config.headers[X-Nonce] nonce config.headers[X-Sign] signature return config })加timestamp和nonce的目的是防重放攻击。如果没有这两个字段攻击者抓到一个合法请求后可以原封不动地反复提交。加上时间戳和随机数之后后端可以校验时间戳是否在有效窗口内以及nonce是否已经使用过这样重放攻击基本就废了。这个方案的签名规则看起来简单但前后端对接时的坑最多。我曾经因为encodeURIComponent对空格的处理方式和后端不一致排查了整整一个下午。建议在项目初期就把签名规则写成设计文档前后端各存一份避免口头约定导致的偏差。3.4 场景三敏感数据本地存储加密除了网络传输本地存储也是敏感信息泄露的重灾区。有些开发同学会把用户手机号、身份证号直接存在localStorage里一旦用户电脑中木马或者浏览器被注入脚本这些数据就全裸了。用AES加密后再存能挡掉很大一部分风险export function setEncryptedStorage(key: string, value: any) { const jsonStr JSON.stringify(value) const encrypted aesEncrypt(jsonStr) localStorage.setItem(key, encrypted) } export function getDecryptedStorageT(key: string): T | null { const encrypted localStorage.getItem(key) if (!encrypted) return null try { const decrypted aesDecrypt(encrypted) return JSON.parse(decrypted) as T } catch (e) { // 解密失败说明数据可能被篡改或密钥已更换 localStorage.removeItem(key) return null } }这里要注意localStorage自带的XSS防护能力是零加密只是增加了一层障碍并不能从根本上解决XSS问题。要真正防住XSS还得配合CSP内容安全策略、对用户输入做严格转义过滤多管齐下才行。4. 常见问题与排查技巧实录4.1 前端加密了后端解不开这是最让人头秃的问题。我自己的排查顺序一般是这样的确认算法模式是否一致。AES的Mode、Padding、IV必须逐一核对一个不match就全废。Java后端默认的AES是ECB模式不带IV而前端我习惯用CBC带IV这俩直接对不上。确认密钥/IV的编码方式是否一致。前端用的是UTF-8字符串Parse成WordArray后端是不是也按UTF-8处理有些后端代码里Key是Hex或Base64编码的那前端就得对应调整。确认密文格式。crypto-js的toString()输出的是OpenSSL格式的Base64字符串里面可能带着U2FsdGVkX1开头的前缀后端如果按标准Base64处理会出问题。这时候可以考虑用CryptoJS.enc.Base64.stringify(encrypted.ciphertext)直接输出纯密文Base64。给大家存一份排查自检清单排查项前端检查后端确认算法AESAES模式CBC还是ECB是否一致填充Pkcs7/Pkcs5PKCS5Padding等偏移量IV是否指定是否一致密钥编码Utf8/Hex/Base64对应处理密文格式是否带前缀是否去前缀4.2 RSA加密长度报错或结果为空jsencrypt加密时如果明文超过密钥长度限制不会报错而是直接返回false。遇到加密结果为false或空字符串别急着怀疑代码先检查是不是明文太长了。2048位RSA密钥最多只能加密245字节。一个中文字符在UTF-8编码下占3个字节所以最多也就加密80多个汉字。如果确实需要加密长文本解决方案是改成混合加密方案——RSA只加密AES密钥长文本交给AES处理。另外还要检查公钥格式。jsencrypt要求公钥必须是-----BEGIN PUBLIC KEY-----包裹的PKCS#8格式如果后端给的是不带换行的裸公钥字符串需要手动补全格式function formatPublicKey(key: string): string { return -----BEGIN PUBLIC KEY-----\n${key.match(/.{1,64}/g)?.join(\n)}\n-----END PUBLIC KEY----- }4.3 MD5加盐还是被猜出来了如果你用的是固定盐值比如vue-advanced这种硬编码字符串那这个盐其实没啥防护价值。因为盐就写在前端代码里攻击者反编译一下就能拿到。更合理的做法是动态盐盐值由后端生成下发每个用户拥有独立的盐或者每次登录使用不同的盐。这样即使攻击者拿到摘要也无法通过预计算的彩虹表反推密码因为每个用户/每次请求的盐都不一样。后端下发的盐可以通过HTTPS传输配合前端加盐算法安全性会有一个质的提升。但要注意盐值一旦下发需要和后端的密码校验逻辑配合——后端的比对逻辑一般是把用户输入的密码和盐拼接后做同样的哈希再和数据库里的摘要比对。这个规则一定要前后端对齐。4.4 加密后性能明显下降前端加密导致的性能问题绝大多数出在RSA上。有一次我在一个高频请求的接口上用了RSA加密整个参数对象页面卡得没法看。后来改成只加密核心敏感字段比如手机号其他参数明文传输体感立刻就流畅了。另外jsencrypt本身是纯JS实现RSA加密大文本时性能尤其差。如果一定要加密长内容可以考虑使用Web Crypto API浏览器原生提供它底层是原生实现性能比纯JS库好很多。但这API的语法比较底层封装成本高需要权衡项目周期。如果是AES加密导致性能问题多半是加密的数据量太大——比如把整个大文件、大图片的Base64都拿去AES加密这就会明显拖慢页面。这种情况应该考虑在前端做分片上传后端再对每个分片解密处理而不是在前端一把梭。4.5 前后端签名永远对不上签名对不上八成是参数序列化规则不一致。比如前端把参数值做了encodeURIComponent后端解析时没有做对应的URL解码或者前端把空值过滤掉了后端却把空值也拼接进了签名串。我的建议是在项目启动阶段就要把签名规则细化到这种程度参数如何排序按ASCII码升序这是行业惯例。值是否做URL编码编码规则是什么。值为null、undefined、空字符串时怎么处理。嵌套对象如何序列化——是JSON字符串还是展开成a.bxx的扁平格式。数组怎么拼接——是用逗号分隔还是key[]value的形式。这些规则一旦定下来就别随意更改。改了前端忘了改后端或者改了后端忘了改前端都能让你排查到怀疑人生。5. 加密方案选型与落地建议六种方式全部看完之后最后聊一点我在真实项目里的选型心得。如果是中小型项目后端接口已经写好了没有太多改造空间那我建议用RSA加密登录密码 SHA-256请求签名这个组合。RSA解决密码裸奔问题SHA-256解决参数篡改问题前后端改动量小安全性却比裸奔好太多。如果是新项目前后端一起设计那我强烈建议直接上AES RSA混合加密方案。虽然实现复杂度高一些但换来的是整体传输内容的机密性——不只是密码而是完整请求体都被加密。而且这套方案有扩展性后续如果要做端到端加密底子是现成的。如果是安全性要求极高的金融、政务类项目前端加密只是整个安全体系的一环。HTTPS、证书双向认证、风控系统、后端脱敏存储、数据库加密这些都得配套上前端加密解决不了系统性的安全问题。最后说一个很多文章不会提的细节加密不等于安全不要把全部筹码押在加密算法上。算法是公开的密钥才是核心。密钥的生成、存储、轮换、吊销每一环都可能成为突破口。前端代码再混淆密钥硬编码在代码里就等于是把保险柜钥匙贴在了保险柜外面。所以真正优秀的方案永远不会让前端的密钥成为系统安全的唯一支柱。这篇文章里所有代码片段我在项目里都实际跑过可以直接复制改造。踩过的坑也都老老实实写出来了希望帮大家少走点弯路。如果后端的同事跟你扯前端加密没意义把文章里讲的风险场景和混合加密方案甩给他实践出真知跑一次抓包对比他心里就有数了。
返回列表