node中的密码安全

2018-09-15 admin

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

为什么需要加密

加密真的有必要吗? 我们先来看一看前端发起的ajax请求中,如果不对密码进行加密,会发生什么。 f12打开chrome开发者工具,找到请求,查看请求参数如下:

clipboard.png

如果你的协议是http,那么前端传给后端的密码差不多是裸奔状态,因为http传输的是明文,很可能在传输过程中被窃听,伪装或篡改。 那么,弄个https不就好了吗? https的确能够极大增加网站的安全性,但是用https得先买证书(也有免费的),对于个人站点或者不想弄证书的情况下,那最起码也得对用户密码进行一下加密吧。

流程图

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

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

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

clipboard.png

注意: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的方法进行解密。

最后

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

clipboard.png

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

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

原文链接:https://segmentfault.com/a/1190000016408673

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-40327.html

文章标题:node中的密码安全

相关文章
Node.js将向移动端扩展
如果你还没有听过Node.js,那么现在就可以了解一下! 目前,来自200多个国家的数以万计的组织在使用Node.js,在Node.js的网站上,每月都有超过200万次下载。但版本发布缓慢使开发人员日益不满,网上出现了创建Node.js分支...
2015-11-12
Node.js v0.11.16 开发版发布
Node.js v0.11.16 开发版发布了,改进记录包括: openssl: Upgrade to 1.0.1l npm: Upgrade to 2.3.0 url: revert support of path for url.fo...
2015-11-12
javascript中的switch语句
switch语句:该语句对表达求值结果和case的值进行比较。如果找到匹配,则程序执行的与该case关联的语句。break为可选参数,通常使用break阻止代码向下一个case执行。switch语句如下: switch (expressio...
2015-11-12
windows 下安装nodejs 环境变量设置
要设置两个东西,一个是PATH上增加node.exe的目录C:\Program Files\nodejs,一个是增加环境变量NODE_PATH,值为C:\Program Files\nodejs\node_modules 一、下载 去nod...
2017-03-18
Node.js深受欢迎的六大原因
Node.js鏄�涓€绉嶅悗璧风殑浼樼�€鏈嶅姟鍣ㄧ紪绋嬭��瑷€锛屽畠鐢ㄦ潵鏋勫缓鍜岃繍琛學eb搴旂敤锛岃繖鍜孉SP.NET锛孯uby聽on聽Rails鎴朣pring妗嗘灦鍋氱殑宸ヤ綔鏄�绫讳技鐨勩€傚畠浣跨敤JavaScript浣滀负涓...
2015-11-11
Node.js实现Excel转JSON
一直在做一个关于网上选课的系统,选用了时下比较流行的node.js。今天在想怎么把学生或者老师的信息导入进去,涉及数量比较多一点,我手边又正好有一部分excel的表格。就想把excel转成json然后倒入到mongodb中去。 搜了下网上的...
2017-03-23
Javascript实现数组中的元素上下移动
交换数组可以实现元素上下移动了,这个效果我们在表格或以前排序算法中都会用到,下面来看一个JavaScript下实现交换数组元素上下移动例子 在写项目的时候,要实现一个数组记录上下移动的示例。写起来也没有没麻烦,无非是交换数组元素。最终实现代...
2017-05-02
Windows系统下使用Sublime搭建nodejs环境
1.下载nodejs,并安装ok后,配置好环境变量。 2.下载sublime text3 3.在package install 包中新增node插件(或者直接去SublimeText-Nodejs插件(https://github.com/...
2017-03-22
nodejs搭建本地服务器并访问文件的方法
安装node:https://nodejs.org/en/download/ 在本地建立目录:f:/nodetest,在该目录下新建index.html作为我们将要访问的内容。新建server.js作为node开启的入口: $ cd f:&...
2017-03-13
JavaScript中的call方法和apply方法使用对比
方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象。 说明: call 方法可以用来代替另一个对象调用一个方法。c...
2017-03-29
回到顶部