参考文章:[https://blog.csdn.net/qq_32674347/article/details/104117594]() github插件:[https://github.com/okoala/egg-jwt]() 后台 ``` // 签发token const token = jwt.sign({ account: '私钥' }, 密钥) ``` 中间件鉴权 ``` // 鉴权 const token = headers['token'] if (!token) { ctx.fail('缺少token,请重新登录') return } const decode = jwt.verify(token, config.signInfo.appSecretTitle) if (!decode || !decode.account) { ctx.fail('没有权限,请重新登录') return } // 注意时间签发Token时的配置时间单位 if (Date.now() - decode.exp > 0) { ctx.fail('Token已过期,请登录') return } // 签名保证数据一致性 const passToken = decode.account const qsStringify = qs.stringify(body, { sort: (a, b) => a.localeCompare(b), encode: false }) const checkSignVal = ctx.helper.sha256(`${apiAccount.timestamp}${passToken}${qsStringify}${apiAccount.nonce}`) if (checkSignVal !== apiAccount.signature) { ctx.fail('签名不一致') return } ``` 前端 ``` // 前置需要内容 import qs from 'qs' import { sha256 } from 'js-sha256' const cryptoRandomString = require('crypto-random-string') const ACCOUNT = '私钥' /** 获取时间戳 精确到秒 */ const getTimesTamp = () => { return Math.floor(Date.now() / 1000) } /** 获取16位随机字符串 随机数六位 + 时间戳秒十位 */ const getRandomString = () => { return `${cryptoRandomString({ length: 6 })}${getTimesTamp()}` } // 遇到请求体比较复杂可以不用序列化,特别要注意中文,多层嵌套等 /** * 签名算法 * 签名结果值 = 签名算法( 时间戳 + password + 序列化请求体 + 随机值 + 时间戳 ) * x-tif-signature = sha256( * x-tif-timestamp * + password * + Query.Stringify(body) * + x-tif-nonce * + x-tif- timestamp) * */ const signatureInterface = (reqData) => { const timeTamp = Math.floor(Date.now() / 1000) const randomString = `${cryptoRandomString({ length: 6 })}${timeTamp}` const qsStringify = qs.stringify(reqData, { sort: (a, b) => a.localeCompare(b), encode: false }) const signature = sha256(`${timeTamp}${ACCOUNT}${qsStringify}${randomString}`) return { 'x-tif-signature': signature, 'x-tif-timestamp': timeTamp, 'x-tif-nonce': randomString } } export default { signatureInterface, getTimesTamp, getRandomString } ```