当前位置:网站首页>Nodejs中使用jsonwebtoken(JWT)生成token的场景使用

Nodejs中使用jsonwebtoken(JWT)生成token的场景使用

2020-11-06 22:11:36 进击的前端

Ⅰ- 壹 - jsonwebtoken简介

一 为什么需要 token

  • http 无状态

  • session 无法跨服务器

  • cors 跨域以后 cookie 无法使用

在前后分离的项目中,每次请求session都会变化,前端调用后端api接口,因此使用cors = require('cors')来解决了跨域问题,而跨域对于cookie来说,就是两个不同的网站,因此session会不停的变。
在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般我们所说的的token大多是指用于身份验证的token

我们需要每次都知道当前请求的人是谁,但是又不想每次都让他提交用户名和密码,这时就需要有一个等同于用户名密码也能够标识用户身份的东西,即—token

二 什么是token

token是由三段式加密字符串组成以.分开例如xxxxxxxxxxxxxxxxxxxxx.yyyyyyyyyyyyyyyyyyyyyyyy.zzzzzzzzzzzzz

  • 第一段: 头, 签证: 安全信息验证, 你的口令, 进行不可逆加密*

  • 第二段: 你要保存的信息: basa64 加密后截取内容,

  • 第三段: 额外信息: 不可逆加密

第一段和第三段不可逆加密 哈希散列,第二段 base64 可逆加密

这一段字符串由后端发给前端,再登陆过以后, 生成一个 token 给到前端

Ⅱ - 贰 - jsonwebtoken的使用

一下载使用

npm i jsonwebtoken
||
yarn add jsonwebtoken

在nodejs中直接导入

// 0. 导入
const jwt = require('jsonwebtoken')

二 jsonwebtoken方法

1 生成token:

jwt.sign(你要保存的信息, 口令, 参数)

  • 保存的信息

  • 口令: 加密口令, 加密的时候混入信息使用, 解密的时候还要这个口令

  • 参数: 是一个对象, {}

    expiresIn: 过期时间,单位为秒 (‘1d’)*

2 解码token:

jwt.verify(你要解析的 token, 口令, 回调函数)

  • token: 必须是一个指定的 token

  • 口令: 必须是加密时候的口令

  • 回调函数: 接收结果

const express = require('express')
const jwt = require('jsonwebtoken')
const cors = require('cors')
const router = express.Router()
const app = express()

app.use(cors())


// 准备一个 token 验证的中间件
app.use(function (req, res, next) {
   
  // req.url 表示当前地址
  const {
    url, headers: {
    authorization: token } } = req
  // const url = req.url
  // const { authorization: token } = req.headers
  // const token = req.headers.authorization

  // 不需要验证的 请求地址
  if (url === '/login' || url === '/banner') return next()

  // 来到这里表示需要 token 验证
  if (!token) return res.send({
    message: '请携带 token 请求', code: 0 })

  jwt.verify(token, 'Josiah', (err, data) => {
   
    if (err && err.message === 'invalid token') return res.send({
    message: '无效 token', code: 0 })

    if (err && err.message === 'jwt expired') return res.send({
    message: 'token 失效', code: 0 })

    next()
  })
})




router.get('/login', (req, res) => {
   
  // 默认登录成功

  const userInfo = {
   
    username: 'XXX',
    age: 18
  }

  // 生成一个 token 返回给前端
  const token = jwt.sign(userInfo, 'Josiah, {
    expiresIn: 60 })

  res.send({
    message: '登录成功', code: 1, token })
})

// 第二次测试
router.get('/cartInfo', (req, res) => {
   

  res.send({
    message: '获取购物车数据成功', code: 1 })
})


router.get('/pay', (req, res) => {
   

  res.send({
    message: '支付成功', code: 1 })
})


// 第一次测试
// router.get('/cartInfo', (req, res) => {
   
  // 你想要购物车数据
  // 那么你必须登录以后
  // 验证 token 是不是正确
  // req, 是本次请求的信息
  // req.headers 就是本次的请求头
  // const token = req.headers.authorization

  // // 1. 有没有
  // if (!token) return res.send({ message: '该请求需要 token', code: 0 })

  // // 2. 对不对
  // jwt.verify(token, 'guoxiang', (err, data) => {
   
  // if (err && err.message === 'invalid token') return res.send({ message: '无效 token', code: 0 })

  // if (err && err.message === 'jwt expired') return res.send({ message: 'token 失效', code: 0 })

  // res.send({ message: '获取购物车数据成功', code: 1 })
  // })

// })

router.get('/banner', (req, res) => {
   
  // 你需要轮播图信息
  // 不需要登录验证

  res.send({
    message: '轮播图数据获取成功', code: 1, list: [ {
   }, {
   } ] })
})

app.use(router)

app.listen(8080, () => console.log('running at 8080'))

三 测试使用

token的生成和解码

// 0. 导入
const jwt = require('jsonwebtoken')
// 准备一个信息
const userInfo = {
   
  _id: '2131245655',
  username: '小星星',
  age: 18,
  gender: '男'
}

// 1. 生成一个 token
const res = jwt.sign(userInfo, 'key', {
    expiresIn: 20 })
console.log(res)
//res会生成一下内容
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
// eyJfaWQiOiIyMTMxMjQ1NjU1IiwidXNlcm5hbWUiOiLpg63nv5QiLCJhZ2UiOjE4LCJnZW5kZXIiOiLnlLciLCJpYXQiOjE1OTkxOTk2MDYsImV4cCI6MTU5OTE5OTYxNn0.
// Cg-PxkAzTnCUF9xja1O9gcOmRzaRsw4TlFM2nCZenAw


// 2. 解码

  jwt.verify(res, 'key', (err, data) => {
   
    console.log('第一次 1.5s')
    if (err) return console.log(err)

    console.log(data)

  })

Ⅲ - 叁 - 第三方插件express-jwt

  • 是一个express框架和jwt结合的第三方中间件
  • 作用:验证token
  • 用这个插件需要和sonwebtoken一起使用

注意:

  1. 如果你要使用 express-jwt你必须有一个全局错误中间件
  2. 正常的 token 返回给前端,需要写成 Bearer token

以下案例用到的插件:

express、jsonwebtoken、express-jwt、cors

app.js

const express = require('express')
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
const cors = require('cors')
const router = expryicisess.Router()
const app = express()


app.use(cors());//解决跨域问题

// app.use() 里面放的 expressJWT().unless()
// 注册 token 验证中间件
app.use(expressJWT({
   
  // 解析口令, 需要和加密的时候一致
  secret: 'Josiah',
  // 加密方式: SHA256 加密方式在 express-jwt 里面叫做 HS256
  algorithms: ['HS256']
}).unless({
   
  // 不需要验证 token 的路径标识符
  path: ['/login', '/banner']
}))



router.get('/login', (req, res) => {
   
  // 默认登录成功

  const userInfo = {
   
    username: '郭翔',
    age: 18
  }

  // 生成一个 token 返回给前端
  const token = 'Bearer ' + jwt.sign(userInfo, 'Josiah', {
    expiresIn: 60 })

  res.send({
    message: '登录成功', code: 1, token })
})

app.use(router)


// 错误处理中间件
app.use((err, req, res, next) => {
   
  res.send({
    err })
})

app.listen(8080, () => console.log('running at 8080'))

login.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>

  <button>登录</button>

  <script>
    // 如果你是做后台管理系统, 一般存储在 sessionStorage
    // window.sessionStorage.setItem('abc', '100')
    
    // 前端携带 token 我们存储在 请求头 里面携带
    // authorization: token

  
    const xhr = new XMLHttpRequest()

    const token = window.localStorage.getItem('token')

    xhr.open('GET', 'http://localhost:8080/cartInfo')

    xhr.onload = function () {
   
      const res = JSON.parse(xhr.responseText)

      console.log(res)
    }

    xhr.setRequestHeader('authorization', token)

    xhr.send()
  </script>
</body>
</html>

0 - 0 - 知识点:

一 在生成token的时候

需要在生成之前添加 Bearer 后面有个空格

const token = 'Bearer ' + jwt.sign(userInfo, 'guoxiang', { expiresIn: 60 })

二在解析token的时候

  • 解析口令, 需要和加密的时候一致
  • 加密方式: SHA256 加密方式在 express-jwt 里面叫做 HS256
// app.use() 里面放的 expressJWT().unless()
// 注册 token 验证中间件
app.use(expressJWT({
  // 解析口令, 需要和加密的时候一致
  secret: 'guoxiang',
  // 加密方式: SHA256 加密方式在 express-jwt 里面叫做 HS256
  algorithms: ['HS256']
}).unless({
  // 不需要验证 token 的路径标识符
  path: ['/login', '/banner']
}))

三 在前端获取的时候

  • 如果你是做后台管理系统, 一般存储在 sessionStorage
  • 前端携带 token 我们存储在 请求头 里面携带,一般使用authorization
  xhr.setRequestHeader('authorization', token)

版权声明
本文为[进击的前端]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4618999/blog/4706905