Node教程——封装一个token验证器

蓝图blueprint,git地址:/github_com/BM-laoli/Node-token-forApi-blueprint

重要说明

本文来源:http://www.ssb52.com/www_2k2k_cc/

老虎机支付宝充值,当我穿着合身、舒适的内衣,我可以从内而外感到性感。詹姆斯是2014年3月3号砍下职业生涯最高的61分;安东尼是2014年1月24号砍下的62分。  大众网继续深入推进“四个转型突破”,用体制创新激发企业活动,用内容创新扩大品牌影响,用运营创新保持收入增长,用技术创新支撑项目建设,培育企业的核心竞争力。今天我第一个讲,大家也知道过去这一个星期对于百度来说是一个非常特殊的星期,感谢朋友们的关心,我们也会非常深刻的反省,希望能够把危机变成机遇,让百度陪大家走得更远一点。

顾命大臣鳌拜武艺高强、功高震主,为少年康熙所忌,为除掉鳌拜,康熙巧设计谋,让韦小宝率一群小太监以戏耍角力为名将鳌拜擒杀。  【同期】(杨洛书年画传承人陈功)  杨洛书老先生是我们的中国年画王,相当于我们中国年画界的泰斗。第三节开始后兰多夫没有回到场上,辽篮单外援阵容对抗青岛双外援阵容,辽篮从本节一开始就失去了对篮板球的控制,进攻连投不中,只靠韩德君造犯规得到2分,一次次的进攻失误给了对手太多的反击机会,客队在第三节还剩9分34秒时打了辽篮一个12比2,辽篮落后了12分,郭士强不得不请求暂停;暂停回来后廉明命中三分,但之后辽篮进攻再次陷入低迷,只有韩德君造犯规得到1分,客队又打了一个9比1,客队以72比55领先,郭士强不得不再次请求暂停,第三节还剩6分47秒;暂停回来后哈德森命中2分,随后之前三分球6投仅有1中的哈德森开始找回手感,郭艾伦、廉明和最后1分18秒替补韩德君出场的卫猛也都开始得分,辽篮进攻端终于恢复正常,与拥有双外援的客队打的难分难解,最后时刻客队外援琼斯命中压哨三分,辽篮以74比89落后进入末节。  【解说】2015年7月20日,宜昌市公安局在工作中发现当地居民姚某通过快递收寄大量包裹,涉及美容药品及医疗器械。

当前,国际形势复杂演变,全球治理深入推进,和平与发展仍是时代主题。桑切斯今年27岁,是智利最当红的球星之一,曾在巴萨效力,获得过无数荣誉。  历史战绩柯洁占优  柯洁的强大在数据上的一个体现在于,面对当代大部分顶尖高手都保持着战绩上的压倒性优势,柁嘉熹也是其中之一,两人历史正式比赛交手六次,柯洁5胜1负,唯一的一负还是在一个国家队内部的擂台赛上。外出比赛时,她发现击剑在吉林省并不被大家熟知,便开始有意接触这项绅士的竞技运动。

这个轮子是 使用 express@5.0 + MongoDB构建起来的一个 node后台通用的验证器,里面主要讲的就是使用jwt,token进行验证,当然你想使用session也没问题,但是这个蓝图工程只包含了token字段内容

首先是初始化我们的项目,

主要是 安装一些东西

  1. 项目的初始化

如下是我们的项目文件夹结构

![img](file://C:\Users\ADMINI~1\AppData\Local\Temp\1589190039(1).jpg)

  1. 项目的包管理

首先我们需要使用express@next框架,因为只用next才能在里面使用async es7的一些东西,
我们还需要mongoose来操作数据库
我们还需要bcrypt对数据库里面的密码进行加密
我们还需要jsonwebtoken快捷的生成token

npm install express@next
npm install mongoose
npm install bcrypt
npm install jsonwebtoken

好了以上就是我们需要做的

设计路由逻辑

首先我们需要在这里设计几个接口,他们是,并且完成post请求的配置解析json

  • 测试接口
  • 注册接口
  • 登录接口
  • 获取所有用户信息接口
  • 等录之后的权限校验接口
  1. 构建入口,并且完成json的解析
    /app.js

const express = require('express');

const app = express();


/解析一遍post参数
app.use(express.urlencoded({ extended: true }))
app.use(express.json())


/路由分发器
app.get('/test', async(req, res) => {
    res.send('测试打通!没问题')
})


app.use('/api', require('./route/index'))


app.listen(3001, async() => {
    console.log('/localhost:3001');
})
  1. 构建分路由

注意这里只是简单的做一些功能测试,后续我们会把这个东西都删掉,把验证丢给router去验证,目的就是模块化处理业务,请求主页不需要token请求管理的页的接口就需要验证

/router/index.js

const express = require('express');

const indexApi = express.Router()


indexApi.post('/register', async(req, res) => {
    console.log(req.body);
    res.send('register!!ok')
})


indexApi.post('/login', async(req, res) => {
    console.log(req.body);
    res.send('login!!ok')
})


indexApi.get('/users', async(req, res) => {
    res.send('users!!ok')
})


indexApi.get('/profile', async(req, res) => {
    res.send('profile!!ok')
})




  1. 完成对应的接口测试
    /.http

@uri = /localhost:3001/api


### 测试
GET {{uri}}

### 展示出所有的用户
GET  {{uri}}/users



###  注册
POST {{uri}}/register
Content-Type: application/json

{
    "username":"user2",
    "password":"123456"
}

### 登录
POST {{uri}}/login
Content-Type: application/json

{
    "username":"user2",
    "password":"123456"
}


### 获取个人信息,传递的是当前保持状态了的用户
GET {{uri}}/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlYjhhNDIzOTM4YzdhNmQ3NDg5ZDJlMyIsImlhdCI6MTU4OTE2MDY0Nn0.UeSGbDgUrQaThemD18iIAGW6t-lc8R_R5tDvFamrgDw


设计实现数据库Model

在这里我们需要完成的工作有:

  • 使用mongoose连上数据库
  • 创建shcema规则
  • 使用规则创建集合
  • 倒出集合操作对象,创建集合交给理由或者中间件去做,这里功能比较简单我们可以直接丢给路由去做,但是为了保持编程的风格一致,我打算丢到中间件里面去

我们把model都写在一个文件里有点不太妥当,当然这样做是完全没有问题的,如果项目有良好的架构我们可以后期考虑把他们分类的去构建model,比如与用户相关的molde都放在一个文件里,等等

/model/model.js

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

mongoose.connect('mongodb:/localhost:27017/express-auth', { useUnifiedTopology: true, useNewUrlParser: true, useCreateIndex: true });


const UserSchma = new mongoose.Schema({

    username: {
        type: String,
        unique: true /只需要usernam为唯一值
    },

    password: {
        type: String,
    }

})

const User = mongoose.model('User', UserSchma) /虽然这个表的名字是User但是实际上数据库创建的时候会给你变成users

/倒出数据操作对象
module.exports = { User }

注意啊,我们只是定义的集合还有数据库的表(集合)操作对象,还米有拿去业务中使用,接下里的章节我们会拿到具体的业务里去使用
好了我们阶段性的回顾一下我们现在的文件夹里面都有哪些东西吧

实现新增(实际上就是注册)用户接口

这里我们定义就能实现我们的业务功能了,首先要说明的是,我们这里依然使用标准化的项目开放方式,把功能写在中间件里,

这里的定义的中间件处理一个专门的业务就是User相关的业务,这是我工作中编写nodejs的全栈项目的一个习惯
/middleware/users.js

const { User } = require('../model/model')

module.exports = {

    register: async(req, res, next) => {
        /console_log(req.body);
        let { username, password } = req.body

        const user = await User.create({
            username: username,
            password: password
        })
        req.user = user

        next()
    }
}

在路由里面你只需要弄这个就好了。实际上中间件就是一个对象

const users = require('../middleware/users')
+++
indexApi.post('/register', users.register, (req, res) => {
    res.send(req.user)
})

+++

实现展示用户功能

前面我们实现了用户的注册新增功能,那么我们就来实现一些查看所有用户功能。
用了前面的架构模式,我们的这个业务就可以全部写在middelwear里了,如果有设计赋值的操作。我们还可以创建一个工具middlewear,来帮助我们实现复杂的功能,这就是模块化开发

/middleware/users.js

+++
 /查看所有用户
    showUser: async(req, res, next) => {

        /为什么是find就可以了,因为mongoose给你封装了
        const user = await User.find();

        req.user = user;
        next();

    }
+++


/router/index.js

const users = require('../middleware/users')
+++
indexApi.get('/users', users.showUser, async(req, res) => {
    res.send(req.user)
})
+++

实现bcrypt加密密码

实际上实现bcrypt的加密非常的简单,只需要调用方法就好了

+++
  password: {
        type: String,
        set(val) { /val是自定义的保存前的加密,返回的值就是加密之后的密码
            return require('bcrypt').hashSync(val, 10) /进行散列之后的密码,10就是加密强度
        }
    }
+++

加密之后的密码验证怎么做?实际上这里就是登录功能

实际上也非常的简单,先验证用户名是否正确 如果正确就去根据用户名查用户数据,然后拿到加密之后的密码,然后使用bcrypt自己的验证方式去验证就好了

/middleware/users.js

+++
   /登录器
    login: async(req, res, next) => {

        let { username, password } = req.body

        const user = await User.findOne({
            username: username
        })

        /验证用户名
        if (!user) {
            return res.status(422).send({ message: '用户名不存在' })
        }
        const isPasswordValid = bcrypt.compareSync(password,
            user.password
        )

        /验证密码
        if (!isPasswordValid) {
            return res.status(422).send({ message: '密码无效' })
        }
        req.user = user
        next()
    }
+++

/router/index.js

indexApi.post('/login', users.login, async(req, res) => {
    res.send(req.user)
})



实现token的下发

实际上这个也非常的简单,我们只需要在登录成功的时候给用户加上一个token就好了

这里的业务逻辑核心,其实就是这个token该如何加

  • 修改一下我们的登录功能,使得用户登录的时候加上一个用以验证用户登录状态的token
    /middleware/users.js
+++
 const jwt = require('jsonwebtoken')
+++

+++
 /登录器
    login: async(req, res, next) => {
    +++

        /生成token,jwtToken   
        /生成签名,我们给id丢进去据好了
    const token = jwt.sign({
            /加密的签名
            id: String(user._id),
            /密钥
        }, 'asdasdasdasdasdasdasdasdasdasdasd') /这个东西实际上是一串秘钥,用来对应每一个的tonken验证器,它应该被写一个单独的文件里
    res.user = {
        user,
        token

    }
    +++
}
  • 我们看一些测试的结果
{
  "user": {
    "_id": "5eb933c9cf3c3f33fcadb560",
    "username": "user2",
    "password": "$2b$10$n2OHQzuSuUtwWpg.YuiDO.FPM4Q9nrBdqANLB3Wkh67P.MonpIyYi",
    "__v": 0
  },
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlYjkzM2M5Y2YzYzNmMzNmY2FkYjU2MCIsImlhdCI6MTU4OTE5Nzc4MX0.a4vrQwTeGsuI320m1OYsjSB8abdxxm8TReKYg6UKbVQ"
}

实现用户的token校验.

这里我们把auth做成一个中间件,这个中间件可以加载需要验证的路由的前面,如果通过验证就放行,要不然就放行next,这就是验证器auth的实现原理,非常的简单
/middleware/auth.js


const jwt = require('jsonwebtoken')
const { User } = require('../model/model')
module.exports = {
    auth: async(req, res, next) => {
        /注意啊这个字段是我们前端需要实现的,因为这是后台要求的
        let raw = String(req.headers.authorization).split(' ').pop() /我为啥要用空格分隔,因为我发起请求的时候多加了一个字段,

        const tokenData = jwt.verify(raw, 'asdasdasdasdasdasdasdasdasdasdasd')
        let { id } = tokenData

        
        /加到req上以便以给下一个中间件使用
        req.user = await User.findById(id)
        
        next()

    }
}

假设我们现在需要把这个auth用于我们的 profile接口做验证,那么我们可以这样来使用

/核心token验证器
indexApi.get('/profile', auth.auth, async(req, res) => {
    res.send(req.user)
})

注意,以上的所有都只是一个小小的demo。正式的打包再我这里

整理好所有的目录,打包构建成蓝图并且发布上git

  • 我为什么要整理成蓝图?因为我希望我的token验证其能复用到很多地方去,假设我以后的项目需要用这个那么我就直接下载蓝图,这样我的token就不用我再去啰嗦的写了,这也实际上已经是一个初步的node框架的雏形了。

我把它写在了blueprint_for_token_v3中。你可以直接git clone去使用它构建你的node项目

优化项目结构打包,我做了那些事?(主要就是以下爱的事情)

  1. 优化目录结构
  2. 整理接口 去掉了没有用的接口,只保留了一些基础的接口
  3. 使用说明:你只需要npm install 就能实现token的验证了,需要验证之后的接口请在admin之后的路由书写,当然你可以自定义路由,拿着我的auth去做验证就可以了
  4. 建议你使用非对称加密的密钥对,进行token的加密,你可以通过引入文件去配置你的加密信息
posted @ 2020-05-11 21:11  老虎机支付宝充值BM老李  阅读(534)  评论(0老虎机支付宝充值编辑  收藏
菲律宾太阳成娱乐管理网 菲律宾太阳网上娱乐99 申博太阳城登入 菲律宾太阳娱乐登入 申博太阳城直营网 申博管理网直营
菲律宾申博娱乐登入 申博会员网址 菲律宾申博游戏登入 申博代理登录 www.38333.com www.msc66.com
太阳城网址 申博免费开户申博线路检测 菲律宾申博直营网 申博太阳城登入 申博注册登入 www.88tyc.com