/** * json web token * @author yutent * @date 2020/09/16 17:23:52 */ import crypto from 'crypto.js' import { base64encode, base64decode, sha1 } from 'crypto.js' const HS256_HEADER = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9' const DEFAULT_CONFIG = { ttl: 3600 * 24 * 7, level: 0, // 校验级别, 0: 不校验客户端, 2: ua, 4: ip, 6: ua + ip secret: 'it_is_secret_key' // jwt密钥, 使用时请修改 } function hmac(str, secret) { let buf = crypto.hmac('sha256', str, secret, 'buffer') return base64encode(buf, true) } export const JwtModule = { name: 'jwt', install(conf = {}) { if (!conf.secret) { console.warn( new Error( 'Please make sure to set the `secret` field, as the default value is not secure' ) ) } let jwt = Object.assign({}, DEFAULT_CONFIG, conf) this.set({ jwt }) return { ttl: jwt.ttl, // 签名, 返回token // header: base64("{"typ":"JWT","alg":"HS256"}") // 这里固定使用sha256 sign(data, secret) { // 加入过期时间, let payload = { data, expires: Date.now() + this.ttl * 1000 } let token = '' payload = base64encode(JSON.stringify(payload), true) token = hmac(`${HS256_HEADER}.${payload}`, secret) return `${HS256_HEADER}.${payload}.${token}` }, // 校验token verify(token = '', secret) { let jwt = token.split('.') let auth, payload if (jwt.length !== 3) { return false } auth = jwt.pop() payload = JSON.parse(base64decode(jwt[1], true)) // 如果已经过期, 则不再校验hash if (payload.expires < Date.now()) { return false } if (hmac(jwt.join('.'), secret) === auth) { return payload.data } return false } } } } export function createJwt() { return function (req, res, next) { let { secret, level } = this.get('jwt') let deviceID = '' let ssid // options请求不处理jwt if (req.method === 'OPTIONS') { return next() } // 校验UA if (level & 2) { deviceID += req.header('user-agent') } // 校验IP if (level & 4) { deviceID += req.ip() } if (deviceID) { deviceID = sha1(deviceID) } req.__mix_key__ = secret + deviceID next() } }