各位掘友好,我是庚云。
在前后端交互中,如果账号密码明文传输,很容易被窃取 ⚠️。虽然 HTTPS 已经可以保证传输安全,但很多业务场景下,我们还会在此基础上 额外增加一层 AES 加密,提升安全性。
今天分享一个完整的 AES 双向加解密 Demo:
- 前端(Vue3 + Vite):加密用户输入的密码,再传给后端
- 后端(Node.js + Express):解密密码,校验登录
- 后端返回一个加密的 token,前端再解密出来
👉 实现一个 前端加密 → 后端解密 → 后端加密 → 前端解密 的完整闭环。
📂 项目结构
bash
aes-demo/
├── backend/ # Node.js + Express 后端
│ ├── index.js # 主入口,API 服务
│ ├── package.json
│ └── node_modules/
│
├── frontend/ # Vue3 前端
│ ├── src/
│ │ ├── api/
│ │ │ └── login.ts # 登录 API
│ │ ├── utils/
│ │ │ └── aes.ts # AES 工具方法(加密/解密)
│ │ ├── views/
│ │ │ └── Login.vue # 登录页面
│ │ ├── main.ts # Vue 应用入口
│ │ └── index.html
│ ├── package.json
│ └── node_modules/
🖥️ 一、后端实现(Node.js 解密)
后端负责:
- 解密前端传过来的密码;
- 验证账号密码;
- 登录成功后,返回一个 加密后的 token。
📁 backend/index.js
javascript
import express from 'express'
import bodyParser from 'body-parser'
import crypto from 'crypto'
import cors from 'cors'
const app = express()
app.use(cors())
app.use(bodyParser.json())
// AES 配置(和前端保持一致)
const KEY = Buffer.from('1234567812345678', 'utf8') // 16 字节
const IV = Buffer.from('8765432187654321', 'utf8') // 16 字节
// 解密
function decryptAES(cipherText) {
const decipher = crypto.createDecipheriv('aes-128-cbc', KEY, IV)
let decrypted = decipher.update(cipherText, 'base64', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}
// 加密
function encryptAES(text) {
const cipher = crypto.createCipheriv('aes-128-cbc', KEY, IV)
let encrypted = cipher.update(text, 'utf8', 'base64')
encrypted += cipher.final('base64')
return encrypted
}
app.post('/api/login', (req, res) => {
const { username, password } = req.body
const decryptedPwd = decryptAES(password)
if (username === 'admin' && decryptedPwd === '123456') {
// 登录成功,返回加密后的 token
const token = encryptAES('this-is-a-secret-token')
res.json({ code: 0, msg: '登录成功', token })
} else {
res.status(401).json({ code: 1, msg: '账号或密码错误' })
}
})
app.listen(3001, () => {
console.log('后端服务已启动:http://localhost:3001')
})
🌐 二、前端实现(Vue3 加密)
前端负责:
- 输入密码 → AES 加密 → 传给后端;
- 拿到后端返回的加密 token → AES 解密 → 得到明文。
📁 frontend/utils/aes.ts
javascript
import CryptoJS from 'crypto-js'
// 和后端约定的 KEY 和 IV
const KEY = CryptoJS.enc.Utf8.parse('1234567812345678')
const IV = CryptoJS.enc.Utf8.parse('8765432187654321')
// 加密
export function encryptAES(text: string): string {
const encrypted = CryptoJS.AES.encrypt(text, KEY, {
iv: IV,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
})
return encrypted.toString()
}
// 解密
export function decryptAES(cipherText: string): string {
const decrypted = CryptoJS.AES.decrypt(cipherText, KEY, {
iv: IV,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
})
return decrypted.toString(CryptoJS.enc.Utf8)
}
📁 frontend/api/login.ts
javascript
import axios from 'axios'
import { encryptAES } from '@/utils/aes'
export function login(username: string, password: string) {
const encryptedPwd = encryptAES(password)
return axios.post('http://localhost:3001/api/login', {
username,
password: encryptedPwd,
})
}
📁 frontend/views/Login.vue
javascript
<template>
<div>
<input v-model="username" placeholder="用户名" />
<input v-model="password" type="password" placeholder="密码" />
<button @click="handleLogin">登录</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { login } from '@/api/login'
import { decryptAES } from '@/utils/aes'
const username = ref('admin')
const password = ref('123456')
const handleLogin = async () => {
try {
const res = await login(username.value, password.value)
if (res.data.code === 0) {
const token = decryptAES(res.data.token)
alert(`登录成功 ✅ 解密后的 token:${token}`)
} else {
alert(res.data.msg)
}
} catch (e) {
alert('登录失败')
}
}
</script>
📁 frontend/main.ts
javascript
import { createApp } from 'vue'
import Login from './views/Login.vue'
createApp(Login).mount('#app')
📁 frontend/index.html
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Login AES Demo</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
📦 前端依赖安装
bash
npm create vite@latest frontend
# 选择 vue-ts 模板
cd frontend
npm install axios crypto-js
npm run dev
🚀 启动流程
bash
# 启动后端
cd backend
npm install express body-parser cors
node index.js
# 启动前端
cd frontend
npm install
npm run dev
输入用户名:admin
,密码:123456
点击登录 → 会弹出 解密后的 token ✅
📝 小结 & 注意事项
到这里,我们实现了一个完整的 AES 双向加解密 Demo:
- 前端输入密码 → AES 加密 → 发给后端
- 后端解密 → 校验账号密码
- 登录成功 → 后端返回加密的 token
- 前端解密 token → 拿到明文
这样一来,即使有人截获了请求数据,也只会拿到密文,进一步提升安全性。
⚠️ 但在真实项目中,还需要注意:
- AES key 长度:必须是 16/24/32 字节,分别对应 AES-128/192/256;
- IV 向量:最好不要写死,而是每次随机生成,再跟密文一起传给对方;
- HTTPS 仍然必须:AES 只是额外的加密层,不能替代 HTTPS;
- 不要重复使用固定 key:可以考虑结合动态密钥、RSA 非对称加密来提升安全性;
- token 更推荐用 JWT:这个 demo 只是展示 AES 使用场景,实际项目中还要结合业务。