node使用jsonwebtoken生成token與驗證是否過期

2023-06-30 18:01:35

場景

我們可以使用 cookie,session,token 來做鑑權。
下面我們來看一下,
如何使用 token 來做鑑權

jwt.sign 的簡單介紹

npm install jsonwebtoken 下載

使用 jsonwebtoken 生成token的基本語法。
jwt.sign(payload, secretOrPrivateKey, [options, callback])
第1個引數 payload:可以是表示有效 JSON 的物件文字、緩衝區,字串。
需要注意的是:如果不是緩衝區或字串,使用 JSON.stringify
下面我們使用物件文字,就不需要使用 JSON.stringify。

第2個引數 secretOrPrivateKey: 是一個字串(utf-8編碼)、緩衝區、物件。
就是說是加密資料。

options:包含的其他選項,如過期時間,
它的選項有:expiresIn 過期時間,如果是數位,單位就是秒。
algorithm: HS256 (預設的演演算法)

callback:回撥函數,包含返回來的錯誤

使用 jsonwebtoken 生成token

// 生成的token。 expiresIn 數值單位預設是秒s
//expiresIn也可以新增為 expiresIn:'10h' | '10d'
let createToken = jwt.sign({
  data: 'jiamideshuju'
}, 'lingpai', { expiresIn: 3 });
//  expiresIn: 3 表示的是有效時間是3s。
console.log('生成的token', createToken)

檢視生成的token是否過期
// 生成的token。
let createToken = jwt.sign({
  data: 'jiamideshuju'
}, 'lingpai', { expiresIn: 3 });

console.log('生成的token', createToken)

setTimeout(()=>{
  // 檢視token是否過期
  var decoded = jwt.verify(createToken, 'lingpai')
  console.log('4s後token是否過期', decoded)
},4000)

封裝生成token與驗證token是否過期

utils/createTokenCheck.js檔案

// 引入 jsonwebtoken
let jwt = require('jsonwebtoken');

let lingpai = 'weislingpai'
const createTokenCheck = {
  // 生成的token。並設定過期時間 
  getToken(jiamiData,expiresIn=3){
    return jwt.sign({
      data: jiamiData
    }, lingpai, { expiresIn: expiresIn })
  },
  // 檢查token是否過期
  verify(token){
    try {
     return jwt.verify(token, lingpai)
    } catch (error) {
      // 如果報錯返回false.[因為token有可能過期,就會報錯]
      console.log('error:', error)
      return false
    }
  }
}
// 暴露出去,其他地方呼叫就行
module.exports = createTokenCheck
app.js檔案呼叫

const createTokenCheck =require('./utils/createTokenCheck')
let token= createTokenCheck.getToken('zhangsan',2)
console.log('不會過期', token)
setTimeout(() => {
  let data=createTokenCheck.verify(token)
  console.log('過期返回false', data)
}, 3000);

登入驗證

前端程式碼
<template>
  <div>
    <h2>登入頁</h2>
    <form action="">
      使用者名稱:<input type="text" v-model="userInfo.user"> <br>
      密  碼:<input type="password" v-model="userInfo.password"><br>
      <button @click="handlerLogin">登入</button>
    </form>
  </div>
</template>

<script setup lang="ts">
import {reactive} from 'vue'
import axios from 'axios'
const userInfo = reactive({
  user:'',
  password:''
})
const handlerLogin=()=>{
  axios.post('http://127.0.0.1:3000/login', {
    user:userInfo.user,
    password: userInfo.password,
  }).then(res => {
      console.log(res);
  }).catch(error => {
      console.log(error);
  });
}
</script>
app.js

app.post('/login',  function(req, res) {
  console.log('req', req.body)
  //通過req.body接收傳遞的引數
  let { user, password } = req.body
  // 我們假設使用者是這樣就會成功
  if(user==='zhangsan'&& password==='123'){
    // 生成token 過期時間設定為10s
    let token= createTokenCheck.getToken('zhangsan',10)
    // 傳送token
    res.send({
      code: 'ok',
      msg:'登入成功',
      token:token
    });
  }else{
    res.send({
      code: 'fail',
      msg: '登入失敗',
    });
  }
})


無法載入響應資料: No data found for resource with given identifier

我們現在需要下載 cors
npm i cors
然後在app.js中引入 
const cors = require('cors')
// 放置在路由的前面
app.use(cors())

'req.body' as it is undefined.

//放置在路由的前面
app.use(express.json());  

前端介面攜帶token

攜帶token

<template>
  <div>
    <h1 class="h1">我是test檔案</h1>
  </div>
</template>

<script setup lang="ts">
import axios from 'axios'
const handlerLogin=()=>{
  axios.post('http://127.0.0.1:3000/list',{},{
    headers:{
      authorization: localStorage.getItem('token')
    }
  }).then(res => {
    console.log(res)
    console.log(res);
  }).catch(error => {
      console.log(error);
  });
}
handlerLogin()
</script>
aap.js程式碼
const createTokenCheck =require('./utils/createTokenCheck')
// 處理跨域
const cors = require('cors')
const express = require('express')
const app = express()
app.use(cors())
// 處理  'req.body' as it is undefined.
app.use(express.json());   
const port = 3000

app.get('/', (req, res) => res.send('Hello World!'))

app.post('/login',  function(req, res) {
  console.log('req', req.body)
  //通過req.body接收傳遞的引數
  let { user, password } = req.body
  // 我們假設使用者是這樣就會成功
  if(user==='zhangsan'&& password==='123'){
    // 生成token 過期時間設定為10s
    let token= createTokenCheck.getToken('zhangsan',10)
    // 傳送token
    res.send({
      code: 'ok',
      msg:'登入成功',
      token:token
    });
  }else{
    res.send({
      code: 'fail',
      msg: '登入失敗',
    });
  }
})

app.post('/list',  (req, res) =>{
  let getToken = (req.headers &&  req.headers.authorization) || ''
  if(getToken){
    // 檢查token是否過期
    if(createTokenCheck.verify(getToken)){
      res.send({
        code: 'ok',
        list: [
          {name:'張三',grade:98, status:'通過考試'},
          {name:'李四',grade:58, status:'未通過考試'},
          {name:'王五',grade:78, status:'通過考試'}
        ]
      });
    }else{
      res.send({
        code: 'fail',
        list: [],
        msg:'token過期'
      });
    }
  }else{
    res.send({
      code: 'fail',
      list: [],
      msg:'請攜帶token'
    });
  }
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))