node中的密码安全(加密)


Posted in Javascript onSeptember 17, 2018

本文将讲解对于前后端分离的项目,前端注册或登录时如何保证用户密码安全传输到server端,最终存入数据库

为什么需要加密

加密真的有必要吗?

我们先来看一看前端发起的ajax请求中,如果不对密码进行加密,会发生什么。

f12打开chrome开发者工具,找到请求,查看请求参数如下:

node中的密码安全(加密)

如果你的协议是http,那么前端传给后端的密码差不多是裸奔状态,因为http传输的是明文,很可能在传输过程中被窃听,伪装或篡改。

那么,弄个https不就好了吗?

https的确能够极大增加网站的安全性,但是用https得先买证书(也有免费的),对于个人站点或者不想弄证书的情况下,那最起码也得对用户密码进行一下加密吧。

流程图

先看一下大体流程图,首先,我们用工具生成公钥和私钥,将其放入server端,前端发起请求获取公钥,拿到公钥后对密码进行加密,然后将加密后的密码发送到server端,server端将用密钥解密,最后再用sha1加密密码,存入数据库。

node中的密码安全(加密)

生成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('私钥已保存!')
})

执行完成后,我们将在根目录下得到公钥和私钥文件:

node中的密码安全(加密)

注意:server端的公钥和密钥应该隔一段时间换一次,比如每次服务器重启时。

前端加密

核心代码如下:

<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自带模块crpto进行解密,当然,你也可以用Node-RSA的方法进行解密。

最后

我们再来看一看前端请求的密码信息:

node中的密码安全(加密)

这样一串字符,即便被他人获取,如果没有密钥,在一定程度上,他是无法知道你的密码的。

当然,关于网络安全是一个大话题,本篇只是对其中的一小部分进行介绍,欢迎留言讨论,希望对您有帮助。,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
用javascript实现页面打印的三种方法
Mar 05 Javascript
事件绑定之小测试  onclick &amp;&amp; addEventListener
Jul 31 Javascript
JS实现可改变列宽的table实例
Jul 02 Javascript
浅谈下拉菜单中的Option对象
May 10 Javascript
jquery实现在网页指定区域显示自定义右键菜单效果
Aug 25 Javascript
js实现的tab标签切换效果代码分享
Aug 25 Javascript
AngularJS定时器的使用与移除操作方法【interval与timeout】
Dec 14 Javascript
js实现水平滚动菜单导航
Jul 21 Javascript
Angular HMR(热模块替换)功能实现方法
Apr 04 Javascript
实例详解ztree在vue项目中使用并且带有搜索功能
Aug 24 Javascript
微信小程序实现导航栏和内容上下联动功能代码
Jun 29 Javascript
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
Aug 05 Vue.js
Vue CLI3搭建的项目中路径相关问题的解决
Sep 17 #Javascript
浅谈webpack SplitChunksPlugin实用指南
Sep 17 #Javascript
vue的过滤器filter实例详解
Sep 17 #Javascript
一步一步的了解webpack4的splitChunk插件(小结)
Sep 17 #Javascript
React Router V4使用指南(精讲)
Sep 17 #Javascript
关于vue编译版本引入的问题的解决
Sep 17 #Javascript
理顺8个版本vue的区别(小结)
Sep 17 #Javascript
You might like
php curl 登录163邮箱并抓取邮箱好友列表的代码(经测试)
2011/04/07 PHP
PHP操作MySQL事务实例
2014/11/05 PHP
Thinkphp3.2.3分页使用实例解析
2016/07/28 PHP
Javascript Math对象
2009/08/13 Javascript
window.onbeforeunload方法在IE下无法正常工作的解决办法
2010/01/23 Javascript
Jquery 选中表格一列并对表格排序实现原理
2012/12/15 Javascript
jquery iframe操作详细解析
2013/11/20 Javascript
js中创建对象的几种方式示例介绍
2014/01/26 Javascript
AngularJS中的模块详解
2015/01/29 Javascript
javascript获取当前的时间戳的方法汇总
2015/07/26 Javascript
JS实现的自定义右键菜单实例二则
2015/09/01 Javascript
JavaScript 实现的 zip 压缩和解压缩工具包Zip.js使用详解
2015/12/14 Javascript
详解Node.js实现301、302重定向服务
2017/04/07 Javascript
详解vue axios中文文档
2017/09/12 Javascript
JS实现手写parseInt的方法示例
2017/09/24 Javascript
微信小程序外卖选购页实现切换分类与数量加减功能案例
2019/01/15 Javascript
深入浅析nuxt.js基于ssh的vue通用框架
2019/05/21 Javascript
python基于multiprocessing的多进程创建方法
2015/06/04 Python
python日期时间转为字符串或者格式化输出的实例
2018/05/29 Python
python 利用pandas将arff文件转csv文件的方法
2019/02/12 Python
windows下安装Python虚拟环境virtualenvwrapper-win
2019/06/14 Python
Django中ajax发送post请求 报403错误CSRF验证失败解决方案
2019/08/13 Python
使用Python-OpenCV消除图像中孤立的小区域操作
2020/07/05 Python
纯css3实现走马灯效果
2014/12/26 HTML / CSS
CSS3色彩模式有哪些?CSS3 HSL色彩模式的定义
2016/04/26 HTML / CSS
HTML5实现移动端弹幕动画效果
2019/08/01 HTML / CSS
生产内勤岗位职责
2013/12/07 职场文书
基层领导干部“四风”问题批评与自我批评
2014/09/23 职场文书
关于清明节的演讲稿2015
2015/03/18 职场文书
民事撤诉申请书范本
2015/05/18 职场文书
家庭贫困证明
2015/06/16 职场文书
2015暑假社会调查报告
2015/07/13 职场文书
Python 内置函数速查表一览
2021/06/02 Python
「Manga Time Kirara MAX」2022年5月号封面公开
2022/03/21 日漫
Android自定义scrollview实现回弹效果
2022/04/01 Java/Android
JavaScript中的LHS和RHS分析详情
2022/04/06 Javascript