Node.js前后端分离架构下的密码安全传输方案
本文详解在前后端分离项目中,如何通过Node.js结合Node-RSA库实现前端密码的安全传输。针对HTTP明文风险,介绍生成公私钥、前端使用jsencrypt加密、后端解密并SHA1存储的完整流程,确保即使数据被截获也无法破解密码。
前后端分离项目中的密码安全传输
本文旨在探讨在前后端分离的项目架构中,前端在用户注册或登录时,如何确保用户密码能够安全地传输至服务器端,并最终安全地存入数据库。
为什么需要加密
加密真的有必要吗?
HTTP明文传输的风险分析
首先分析前端发起的ajax请求,若不对密码进行加密处理,可能会引发何种安全风险。
按下f12打开chrome开发者工具,定位到具体的网络请求,查看其请求参数详情如下:

若网站协议仅为http,前端传输给后端的密码实际上处于裸奔状态。由于http传输的是明文数据,在传输过程中极易被窃听、伪装或篡改。
那么,直接启用https不就可以解决问题了吗?
https确实能显著提升网站安全性,但获取证书通常需要购买(尽管存在免费选项)。对于个人站点或不愿配置证书的场景,至少应对用户密码进行加密处理。
流程图
首先概览整体流程:利用工具生成公钥和私钥并存入服务器;前端发起请求获取公钥;获取公钥后对密码进行加密;将加密后的密码发送至服务器;服务器使用私钥解密;最后对解密后的密码进行sha1加密,并存储至数据库。

Node.js环境下RSA密钥生成
生成RSA公钥和密钥
既然选定RSA加密,首先需要相应的工具。常见的工具有openssl,此处不作介绍,感兴趣者可自行查阅。针对node环境,推荐一个优秀的库Node-RSA,我们将利用它来生成RSA公钥和私钥。
RSA是一种非对称加密算法,即由一个密钥和一个公钥构成的密钥对。其机制为通过密钥加密、公钥解密,或通过公钥加密、密钥解密。其中,公钥可以公开,密钥必须保密。
使用Node-RSA生成的公钥和私钥代码如下:
const NodeRSA = require('node-rsa')
const fs = require('fs')
// Generate new 512bit-length key
var key = new NodeRSA({b: 512})
key.setOptions({encryptionScheme: 'pkcs1'})
var privatePem = key.exportKey('pkcs1-private-pem')
var publicDer = key.exportKey('pkcs8-public-der')
var publicDerStr = publicDer.toString('base64')
// 保存返回到前端的公钥
fs.writeFile('./pem/public.pem', publicDerStr, (err) => {
if (err) throw err
console.log('公钥已保存!')
})
// 保存私钥
fs.writeFile('./pem/private.pem', privatePem, (err) => {
if (err) throw err
console.log('私钥已保存!')
})
执行上述代码后,我们将在根目录下获得公钥和私钥文件:

注意:服务器端的公钥和私钥应定期更换,例如每次服务器重启时进行更新。
前端加密实现
前端加密
核心代码如下:
<script src="https://cdn.bootcss.com/jsencrypt/2.3.1/jsencrypt.min.js"></script>
<script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script>
<script>
function reg() {
axios({
method: 'post',
url: 'http://127.0.0.1:3000/getPublicKey'
})
.then(res => {
let result = res.data
// 从后端获取的公钥 String
var publicPem = result
// 用JSEncrypt对密码进行加密
var encrypt = new JSEncrypt()
encrypt.setPublicKey(publicPem)
var password = 'abc123'
password = encrypt.encrypt(password)
axios({
method: 'post',
url: 'http://127.0.0.1:3000/reg',
data: {
password: password
}
})
.then(res => {
let result = res.data
console.log(result)
})
.catch(error => {
console.log(error)
})
})
}
</script>
前端将使用jsencrypt库进行加密操作,详细用法请参考github文档。
后端解密与存储
后端解密
后端核心代码:
const express = require('express');
const crypto = require('crypto');
const fs = require('fs');
var privatePem = fs.readFileSync('./pem/private.pem');
var app = express();
app.use(express.json());
// CORS 注意:要放在处理路由前
function crossDomain(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use(crossDomain)
app.use(function (req, res, next) {
// 不加会报错
if (req.method === 'OPTIONS') {
res.end('ok')
return
}
switch (req.url) {
case '/getPublicKey':
let publicPem = fs.readFileSync('./pem/public.pem', 'utf-8')
res.json(publicPem)
break
case '/reg':
// 解密
var privateKey = fs.readFileSync('./pem/private.pem', 'utf8')
var password = req.body.password
var buffer2 = Buffer.from(password, 'base64')
var decrypted = crypto.privateDecrypt(
{
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PADDING // 注意这里的常量值要设置为RSA_PKCS1_PADDING
},
buffer2
)
console.log(decrypted.toString('utf8'))
// sha1加密
var sha1 = crypto.createHash('sha1');
var password = sha1.update(decrypted).digest('hex');
console.log('输入到数据库中的密码是: ', password)
// 存入数据库中
// store to db...
res.end('reg ok')
break
}
})
app.listen(3000, '127.0.0.1')
此处使用node自带模块crypto进行解密,当然,也可以使用Node-RSA的方法进行解密。
最后
再次查看前端请求的密码信息:

这样一串字符,即便被他人获取,若没有密钥,在一定程度上,攻击者无法得知你的原始密码。
当然,网络安全是一个宏大话题,本篇仅对其中的一个小部分进行介绍,欢迎留言讨论,希望对您有所帮助,也希望大家多多支持本站。
NestJS 是什么?与 Express、Koa 的核心区别及选型建议
2026-11-05 13:46:41
生产环境升级 Node.js 的注意事项与兼容性测试策略
2026-11-05 09:19:24
nvm 常用命令详解:怎么平滑切换和升级 Node.js 版本
2026-11-04 09:02:34
JavaScript和JSP的根本区别:运行环境与执行机制解析
2026-11-03 23:30:18
使用nvm卸载指定版本Node.js并切换默认环境
2026-11-03 23:09:26
