微信小程序之(zhī)無感知刷新token - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關 >

微信小程序之(zhī)無感知刷新token

發表時(shí)間:2021-1-4

發布人(rén):融晨科技

浏覽次數:176

一.接口調用憑證token

微信小程序授權登錄之(zhī)後,會成生成token返回給客戶端,客戶端取得token之(zhī)後,作爲(wéi / wèi)後續一系列接口的(de)調用憑證,然後,服務器返回給客戶端的(de)token會有一個(gè)有效期,token一但過期,就(jiù)會導緻客戶端後續的(de)接口調用失敗,因此,在(zài)調用接口之(zhī)前,我們需要(yào / yāo)保證token是(shì)有效的(de),這(zhè)樣才能保證客戶端的(de)功能不(bù)會因爲(wéi / wèi)token過期而(ér)導緻異常


二.微信授權登錄、token合法性及有效性校驗

token合法性及有效性校驗

const Router = require('koa-router')
const router = new Router()
const { verifyToken } = require('../../../../utils/utils')
const User = require('../../../../model/user')

router.post('/api/v1/member/verify', async (ctx, next) => {
    const token = ctx.request.header.token
    //驗證token是(shì)否過期
    const decoded = verifyToken(token)
    
    const res = await User.findByOpenID(decoded.openid)
    if(!res) {
        //用戶不(bù)存在(zài)
        throw new global.errors.UserNotFoundException()
    }

    ctx.body = {
        code: 0,
        msg: "token有效"
    }
})

module.exports = router
const jwt = require('jsonwebtoken');
const verifyToken = function(token, secret) {
    let decoded
    try {
        decoded = jwt.verify(token, 'com_aykj_gale');
    } catch(error) {
        let err = new global.errors.ForbiddenException()
        if(error.name == 'TokenExpiredError') {
            err.msg = 'token已過期'
            err.errorCode = 10006
        } else {
            err.msg = 'token不(bù)合法'
            err.errorCode = 10005
        }
        throw err
    }
    
    return decoded
}
/api/v1/member/code2token: 登錄獲取token
/api/v1/member/register: 注冊
/api/v1/member/verify: token合法性及有效性校驗
/api/v1/member/member_index: 獲取用戶信息,後續會基于(yú)此接口,實現token的(de)無感知刷新
三.微信小程序中請求接口

// /project_directory/config.js
const serverUrl = 'http://192.168.1.111:3000'

const config = {
  code2token: `${serverUrl}/api/v1/member/code2token`,
  register: `${serverUrl}/api/v1/member/register`,
  verify: `${serverUrl}/api/v1/member/verify`,
  memberIndex: `${serverUrl}/api/v1/member/member_index`
}

module.exports = config
// /project_directory/utils/http-service.js
class HttpService {
  constructor(){}

  get(url, params, headers) {
    if(!headers) {
      headers = {}
    }
    return this._request(url, 'GET', params, headers)
  }

  postJson(url, params, headers) {
    if(!headers) {
      headers = {}
    }
    headers['content-type'] = 'application/json'
    return this._request(url, 'POST', params, headers)
  }

  postForm(url, params, headers) {
    if(!headers) {
      headers = {}
    }
    headers['content-type'] = 'application/x-www-form-urlencoded'
    return this._request(url, 'POST', params, headers)
  }

  _request(url, method, params, headers) {
    return new Promise((resolve, reject) => {
      wx.request({
        url: url,
        method: method,
        data: params,
        header: headers,
        complete: function(res) {
          var errMsg = res.errMsg //request:ok;request:fail
          if(errMsg != "request:ok") {
            var reason = {
              code: -1,
              msg: "請求超時(shí)"
            } 
            reject(reason)
          } else {
            var resData = res.data
            var resDataCode = resData.code
            if(resDataCode != undefined) {
              if(resDataCode == 0) {
                resolve(resData)
              } else {
                reject(resData)
              }
            } else {
              var reason = {
                code: -1,
                msg: resData
              }
              reject(reason)
            }
          }
        }
      })
    })
  }
}

module.exports = HttpService
// /project_directory/http/request-center.js
import HttpService from "../utils/http-service"
import config from "../config"
const tokenKey = "token"
class RequestCenter {
  constructor() {
    this.httpService = new HttpService()
  }
  register(params, headers) {
    return this.httpService.postJson(config.register, params, headers)
  }
  code2token(params, headers) {
    return this.httpService.postJson(config.code2token, params, headers)
  }
  verifyToken(params, headers) {
    return this.httpService.postJson(config.verify, params, headers)
  } 

  memberIndex(params, headers) {
    return this.httpService.postJson(config.memberIndex, params, headers)
  }

  wxLogin() {
    return new Promise((resolve, reject) => {
      wx.login({
        complete: function(res) {
          if(res && res.code) {
            resolve(res.code)
          } else {
            reject({
              code: -1,
              msg: "wx.login 失敗"
            })
          }
        }
      })
    })
  }
  
}

const requestCenter = new RequestCenter()
module.exports = requestCenter
// /project_directory/pages/index/index.js
const app = getApp()

Page({
  data: {
    
  },

  onLoad: async function(res) {
    var token = wx.getStorageSync('token')
    if(!token) {
      wx.reLaunch({
        url: '/pages/auth/auth',
      })
    } else {
      var headers = {}
      headers["token"] = wx.getStorageSync('token')
      await getApp().global.requestCenter.memberIndex({}, headers)
    }
  }
})

四.無感知刷新token

// /project_directory/http/request-center.js
import HttpService from "../utils/http-service"
import config from "../config"

const tokenKey = "token"

class RequestCenter {

  ...

  memberIndex(params, headers) {
   return this._verify(params, headers, () => {
      return this.httpService.postJson(config.memberIndex, params, headers)
    })
  }

  wxLogin() {
    return new Promise((resolve, reject) => {
      wx.login({
        complete: function(res) {
          if(res && res.code) {
            resolve(res.code)
          } else {
            reject({
              code: -1,
              msg: "wx.login 失敗"
            })
          }
        }
      })
    })
  }
  
  _verify(params, headers, fun) {
    if(headers && headers[tokenKey]) {
      return new Promise((resolve, reject) => {
        //驗證token是(shì)否過期
        this.verifyToken(params, headers).then((res) => {
          //token未過期,繼續上(shàng)一次請求
          fun().then((res) => {
            resolve(res)
          }, (reason) => {
            reject(reason)
          })
        }, (reason) => {
          var code = reason.code
          if(code == 10006) {
            //token過期,刷新token,繼續上(shàng)一次請求
            this.wxLogin().then((res) => {
              this.code2token({code:res}, {}).then((res) => {
                var token = res.token
                wx.setStorageSync('token', token)
                headers[tokenKey] = token
                fun().then((res) => {
                  resolve(res)
                }, (reason) => {
                  reject(reason)
                })
              }, (reason) => {
                reject(reason)
              })
            }, (reason) => {
              reject(reason)
            })
          } else {
            reject(reason)
          }
        })
      })
    } else {
      return fun()
    }
  }
  
}
const requestCenter = new RequestCenter()
module.exports = requestCenter

相關案例查看更多