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 插件模板 制作jquery插件的朋友可以参考下
Mar 17 Javascript
File, FileReader 和 Ajax 文件上传实例分析(php)
Apr 27 Javascript
js单向链表的具体实现实例
Jun 21 Javascript
Angular中的Promise对象($q介绍)
Mar 03 Javascript
JS函数的几种定义方式分析
Dec 17 Javascript
jQuery绑定事件on()与弹窗的简要概述
Apr 27 Javascript
JS图片放大效果简单实现代码
Sep 08 Javascript
JavaScript动态检验密码强度的实现方法
Nov 09 Javascript
vue2手机APP项目添加开屏广告或者闪屏广告
Nov 28 Javascript
ES6小技巧之代替lodash
Jun 07 Javascript
jQuery实现轮播图源码
Oct 23 jQuery
vue+node 实现视频在线播放的实例代码
Oct 19 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
flash用php连接数据库的代码
2011/04/21 PHP
php&amp;mysql 日期操作小记
2012/02/27 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
2018/06/16 PHP
定义select的边框颜色
2008/04/28 Javascript
Nodejs实现多人同时在线移动鼠标的小游戏分享
2014/12/06 NodeJs
jQuery异步获取json数据方法汇总
2014/12/22 Javascript
JQuery中DOM事件合成用法实例分析
2015/06/13 Javascript
在页面中输出当前客户端时间javascript实例代码
2016/03/02 Javascript
原生JavaScript实现Ajax的方法
2016/04/07 Javascript
jQuery简单实现iframe的高度根据页面内容自适应的方法
2016/08/01 Javascript
Ajax与服务器(JSON)通信实例代码
2016/11/05 Javascript
Angularjs 与 bower安装和使用详解
2017/05/11 Javascript
vue 项目常用加载器及配置详解
2018/01/22 Javascript
Bootbox将后台JSON数据填充Form表单的实例代码
2018/09/10 Javascript
详解Vue实战指南之依赖注入(provide/inject)
2018/11/13 Javascript
vue实现的树形结构加多选框示例
2019/02/02 Javascript
简单了解JavaScript中常见的反模式
2019/06/21 Javascript
Vue实战教程之仿肯德基宅急送App
2019/07/19 Javascript
[02:22]完美世界DOTA2联赛PWL S3 集锦第一期
2020/12/15 DOTA
python json.loads兼容单引号数据的方法
2018/12/19 Python
Python获取航线信息并且制作成图的讲解
2019/01/03 Python
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
2019/04/09 Python
使用 Python 遍历目录树的方法
2020/02/29 Python
Python根据字符串调用函数过程解析
2020/11/05 Python
浅谈CSS3鼠标移入图片动态提示效果(transform)
2017/11/06 HTML / CSS
Vince官网:全球著名设计师品牌,休闲而优雅的服饰
2017/01/15 全球购物
Nike荷兰官方网站:Nike.com (NL)
2018/04/19 全球购物
澳洲健康食品网上商店:Aussie Health Products
2018/06/15 全球购物
Myprotein台湾官方网站:全球领先的运动营养品牌
2018/12/10 全球购物
联强国际笔试题面试题
2013/07/10 面试题
自我评价怎么写正确呢?
2013/12/02 职场文书
文明风采获奖感言
2014/02/18 职场文书
2014年小学图书室工作总结
2014/12/09 职场文书
2015年汽车销售经理工作总结
2015/04/27 职场文书
解决Pytorch dataloader时报错每个tensor维度不一样的问题
2021/05/28 Python
pycharm部署django项目到云服务器的详细流程
2021/06/29 Python