node脚手架搭建服务器实现token验证的方法


Posted in Javascript onJanuary 20, 2021

内容

  • 用脚手架快速搭建 node 项目
  • 用 mysql 连接池实现与数据库的交互
  • 用 jsonwebtoken 实现 token 身份验证
  • 综合案例:用简介登录页面实现上述内容

1. 快速搭建 node 项目

我们都知道 express 框架可高效的开发 node 服务器,但对于底层的搭建还要靠自己手写。然而 express-generator 的出现就很好地解决了此问题,它可一键为我们生成项目基本骨架,可谓node 脚手架

1.1 生成项目

①:首先全局安装 express : npm install express -g
②:接着全局安装 express-generator:npm install express-generator -g
③:然后使用命令创建项目: express token_learn(项目名称)

1.2 修改入口文件

对于好多习惯了手撸服务器的人,app.js 总是让人难忘,奈何此骨架中入口文件为 www.js。此时我们可以手动修改app.js 代码,让其成为我们的入口文件

示例:

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');

const index = require('./routes/index');
const users = require('./routes/users');

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);

app.listen(3000, () => console.log('server is run 3000'))

2. 连接mysql 数据库

此处采用连接池的方式进行连接(高效安全)

2.1 创建连接

①:安装 mysql 模块:npm i mysql
②:在项目根目录下配置连接池

首先在项目根目录下创建 util 文件夹,文件夹下创建 bdconfig.js 文件

bdconfig.js

const mysql = require('mysql');

module.exports = {
  mysqlParams: {
    host: 'localhost', //域名
    port: '3306', //端口
    user: 'root', //用户名
    password: 'myroot', //密码
    database: 'nodeapi' //数据库
  },
  sySqlConnect(sql, sqlArr) {
    return new Promise((resolve, reject) => { //用Promise对象将其改造,方便接收数据
      const pool = mysql.createPool(this.mysqlParams);
      pool.getConnection((err, conn) => {
        if (err) {
          reject(err)
        } else {
          conn.query(sql, sqlArr, (err, data) => { //操作数据库
            if (err) {
              reject(err)
            } else {
              resolve(data)
            }
          })
          conn.release() //释放连接
        }
      })
    })
  }
}

2.2 使用连接

使用时只需要传入 sql(sql语句)、sqlArr(参数),通过Promise 改造后可直接用返回值拿到结果

3. token 身份验证

随着web 的发展,session、cookie 的验证方式弊端也愈发突出,此时token孕育而生,token的强大不仅限于其是无状态的,还在于它可以跨域

3.1 实现步骤

①:首先安装 jsonwebtoken 模块:npm i jsonwebtoken
②:接着在项目中使用该模块

const dbConfig = require('../util/dbconfig');
const jwt = require('jsonwebtoken');
const secret = 'login-rule'; //秘钥规则(自定义)

token = async(req, res, next) => { //定义token验证中间件函数(应用于除登录外的每个请求)
  if (req.headers.authorization) {
    const token = req.headers.authorization;
    const { id, username } = jwt.verify(token, secret); // 对token进行解密查找
    let sql = 'select * from test where id=?';
    let sqlArr = [id];
    let result = await dbConfig.sySqlConnect(sql, sqlArr);
    if (result.length === 0) {
      res.status(200).send({ msg: '用户错误' })
      return
    }
    if (username !== result[0].username) {
      res.status(200).send({ msg: '用户错误' })
    } else {
      next()
    }
  } else {
    res.status(200).send({ msg: '无效请求头' })
  }
}

login = async(req, res) => { //定义登录接口(因为这个请求头不携带token,所以引用在token验证中间件之前)
  let { username, password } = req.body;
  let sql = 'select * from test where username=?';
  let sqlArr = [username];
  let result = await dbConfig.sySqlConnect(sql, sqlArr);
  if (result.length) {
    if (password === result[0].password) {
      const { id, username } = result[0];
      //对token进行加密响应个客户端(参数1:传值规则;参数2:加密规则; 参数3:定义时间)
      const token = jwt.sign({ id, username }, secret, { expiresIn: 60 * 60 });
      res.status(200).send({ msg: '登陆成功', token: token, status: 200 });
    } else {
      res.status(200).send({ msg: '登陆失败', status: 422 });
    }
  } else {
    res.status(200).send({ msg: '用户名不存在', status: 401 })
  }
}

// 验证身份中间件
module.exports = {
  token,
  login
}

③:在 app.js 中进行配置

// 写在 app.use() 之后,路由之前
app.use('/users/loginjwt', token.login); //登录接口(无需验证token,所以写在token中间件之前)
app.use(token.token);

4. 案例实现 token

4.1 原理阐述

为确保身份唯一且有效:用户每次发送登录请求且登录成功,服务器端都会响应给用户一个含用户信息(唯一)的加密 token(字符串),此时用户接收到 token,并把 token 存储在 sessionStorage 或 localStorage中(此处为)。同时用户每次发送其他请求时,在请求头中携带本地的 token,服务器端 token验证中间件拦截请求,对 token进行解密,得到用户信息并与数据库比对,信息存在则放行(身份验证成功)。

4.2 效果预览

node脚手架搭建服务器实现token验证的方法

4.3 开始实现

写简洁静态页面,且实现ajax 请求

login.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="../javascripts/jquery.min.js"></script>
  <title>Document</title>
</head>

<body>
  <form id="loginform">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" value="登录">
  </form>
  <script>
    $(function() {
      $('#loginform').on('submit', function() {
        const formdata = $(this).serialize()
        $.ajax({
          url: '/users/loginjwt',
          type: 'post',
          data: formdata,
          success(res) {
            if (res.status === 200) {
              window.sessionStorage.setItem('token', res.token);
              location.href = '/user/index.html'
            }
          }
        })
        return false
      })
    })
  </script>
</body>
</html>

index.html

<script>
  if (!sessionStorage.getItem('token')) {
    location.href = '/user/login.html'
  }
</script>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="../javascripts/jquery.min.js"></script>
  <title>Document</title>
</head>

<body>
  <h1>welcome index</h1>
  <a href="javascript:;" rel="external nofollow" >退出登录</a>
  <script>
    $(function() {
      $.ajaxSetup({
        // 发送请求前触发
        beforeSend(xhr) {
          // 在此设置自定义请求头
          xhr.setRequestHeader('authorization', sessionStorage.getItem('token'))
        }
      })
      $.ajax({
        url: '/users',
        success(res) {
          console.log(res);
        }
      })
      $('a').on('click', function() {
        sessionStorage.clear();
        location.href = '/user/login.html'
      })
    })
  </script>
</body>
</html>

4.4 注意点

值得注意的是,对于 本地 token 的验证(是否存在)一定要写在页面最顶端(防止页面加载,再次发送用户列表请求)
对于 ajax请求头,一个一个加真的很烦,此处用 $ajaxSetup方法,修改ajax 的默认配置 。配置过后,写在其下边的 ajax 请求,都会带上请求头。

到此这篇关于node脚手架搭建服务器实现token验证的方法的文章就介绍到这了,更多相关node token验证 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Jquery api 速查表分享
Jan 12 Javascript
JavaScript获取表单enctype属性的方法
Apr 02 Javascript
JS实现上下左右对称的九九乘法表
Feb 22 Javascript
AngularJS基础 ng-dblclick 指令用法
Aug 01 Javascript
深入理解JS实现快速排序和去重
Oct 17 Javascript
jQuery实现的无缝广告图片左右滚动功能详解
Dec 24 Javascript
Vue.js对象转换实例
Jun 07 Javascript
webpack源码之loader机制详解
Apr 06 Javascript
Vue中的transition封装组件的实现方法
Aug 13 Javascript
layer.open的自适应及居中及子页面标题的修改方法
Sep 05 Javascript
layui table单元格事件修改值的方法
Sep 24 Javascript
在Vue中创建可重用的 Transition的方法
Jun 02 Javascript
Vue实现图书管理案例
Jan 20 #Vue.js
浅析JavaScript中的事件委托机制跟深浅拷贝
Jan 20 #Javascript
详解vue之自行实现派发与广播(dispatch与broadcast)
Jan 19 #Vue.js
js实现电灯开关效果
Jan 19 #Javascript
jquery实现穿梭框功能
Jan 19 #jQuery
jQuery实现穿梭框效果
Jan 19 #jQuery
element el-table表格的二次封装实现(附表格高度自适应)
Jan 19 #Javascript
You might like
剖析 PHP 中的输出缓冲
2006/12/21 PHP
ThinkPHP模板判断输出Empty标签用法详解
2014/06/30 PHP
搭建基于Docker的PHP开发环境的详细教程
2015/07/01 PHP
PHP mysql事务问题实例分析
2016/01/18 PHP
在JavaScript中遭遇级联表达式陷阱
2007/03/08 Javascript
JavaScript 无符号右移赋值操作
2009/04/17 Javascript
关于Aptana Studio生成自动备份文件的解决办法
2009/12/23 Javascript
JQuery select标签操作代码段
2010/05/16 Javascript
JS将数字转换成三位逗号分隔的样式(示例代码)
2014/02/19 Javascript
js实现延迟加载的方法
2015/06/24 Javascript
简单介绍jsonp 使用小结
2016/01/27 Javascript
JavaScript编程学习技巧汇总
2016/02/21 Javascript
JavaScript中setTimeout和setInterval函数的传参及调用
2016/03/11 Javascript
Nodejs进阶:核心模块net入门学习与实例讲解
2016/11/21 NodeJs
Javascript设计模式之装饰者模式详解篇
2017/01/17 Javascript
JavaScript中动态向表格添加数据
2017/01/24 Javascript
详解Vue + Vuex 如何使用 vm.$nextTick
2017/11/20 Javascript
微信小程序模板template简单用法示例
2018/12/04 Javascript
vue模仿网易云音乐的单页面应用
2019/04/24 Javascript
[05:05]给小松五分钟系列 第二期介绍为什么打DOTA2
2014/07/02 DOTA
[01:55]《走出家门看比赛》——DOTA2 2015国际邀请赛同城线下观战
2015/07/18 DOTA
介绍Python中内置的itertools模块
2015/04/29 Python
Python字典简介以及用法详解
2016/11/15 Python
TensorFlow模型保存/载入的两种方法
2018/03/08 Python
pycharm新建一个python工程步骤
2019/07/16 Python
用CSS3实现无限循环的无缝滚动的实例代码
2017/07/04 HTML / CSS
美国时尚在线:Showpo
2017/09/08 全球购物
马来西亚在线时尚女装商店:KEI MAG
2017/09/28 全球购物
企业宣传策划方案
2014/05/29 职场文书
春秋淹城导游词
2015/02/11 职场文书
毕业季聚会祝酒词!
2019/07/04 职场文书
python OpenCV学习笔记
2021/03/31 Python
你知道哪几种MYSQL的连接查询
2021/06/03 MySQL
用php如何解决大文件分片上传问题
2021/07/07 PHP
HTML常用标签超详细整理
2022/03/19 HTML / CSS
把77A收信机改造成收音机
2022/04/05 无线电