jwt介绍,以及在node和koa中的应用

JWT

JSON Web Token( JWT)是目前最流行的跨域认证解决方案。

一般的跨域认证方式

流程如下:

  1. 客户端向服务器发送用户名和密码
  2. 服务器验证通过后,在session中保存相关数据
  3. 服务器向客户端返回一个session_token放到cookie中
  4. 客户端每次请求都通过cookie携带session_token
  5. 服务器拿到session_token,通过这个找到以前存的用户信息,进行判断

上面session中存放的数据,通过数据库或者别的持久化操作存储,但是会存在服务器集群数据同步的问题,处理起来比较麻烦。

JWT原理

服务器拿到用户登录信息,验证通过后会根据用户信息去生成一个Token并携带Signature返回给用户,服务器不存储session的信息,交由用户去存储。

JWT组成

xxxxx.yyyyy.zzzzz对应的依次如下

  • Header
  • Payload
  • Signature

中间通过.分隔:Header.Payload.Signature

Header

使用的是Base64URL 算法转成字符串,解析后是个JSON对象,描述JWT的元数据

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload

使用的是Base64URL 算法转成字符串,解析后是个JSON对象,存放JWT需要传输的信息

  • iss 签发人
  • exp 过期时间
  • sub 主体信息
  • iat 签发时间
  • aud 受众
  • nbf 生效时间
  • jti 编号

注意,JWT 默认是不加密的,任何人都可以读到,所以不要把重要信息放在这个部分。

Signature

使用你需要的加密方式(默认HMAC SHA256加密)

HMACSHA256(base64UrlEncode(Header) + "." +base64UrlEncode(Payload),secret)

JWT客户端发送

客户端收到服务器返回的Token,存储在cookie、sessionStorage或者localStorage中

在需要认证的时候,将Token添加到Http请求的Header中

Header: {
    Authorization: `Bearer ${Token}`
}

注意, Bearer和Token之间有个空格

在node中使用jwt

node-jsonwebtoken

jsonwebtoken是JWT的node版本 github

  1. 安装
yarn add jsonwebtoken
  1. 生成Token
const jwt = require('jsonwebtoken')

const token = jwt.sign({
    // 设置一个小时的过期时间   
    exp: Math.floor(Date.now() / 1000) + 3600,
    // 自定义的携带信息
    data: {
        name: user.name,
        createTime: user.createTime
    }
}, 'demo')
  1. JWT验证
jwt.verify(token, 'demo', (err, decode) => {
    // decode是携带的信息
    if (err) {
    // 认证失败
    // ...    
    } else {
    // 成功
    // ...
    }
})
  1. 路由权限验证

由于本人使用的是koa搭建的服务端,所以下面是基于koa的操作

const koa = require('koa')
const Router = require('koa-router')
const bodyParser = require('koa-bodyparser')
const jwtKoa = require('koa-jwt')

const app = new koa()
const router = new Router()

app.use(bodyParser())

// JWT拦截

/**
 * secret是服务端存储的密钥
 * unless是不做JWT验证的条件
 * unless.method 不做验证的请求方式 这里是所有的GET请求不去做拦截
 * unless.path 不做验证的请求路径 这里是/login请求不去做拦截
 *
*/

// 特殊路径处理,这里的login用的是post
const specialPath = new RegExp(`^\/login`)
app.use(jwtKoa({ secret: 'demo' }).unless({ method: ['GET'], path: [specialPath] }))


router.get('/demo',(ctx, next) => {
    
})
router.post('/demo', (ctx, next) => {
    
})
router.del('/demo/:id', (ctx, next) => {
    
})
router.put('/demo/:id',(ctx, next) => {
    
})

app.use(router.routes()).use(router.allowedMethods())

jsonwebtoken 文档

jwt.sign(payload, secretOrPrivateKey, [options, callback])

  • 异步:如果提供回调,则使用err或JWT 调用回调。

  • 同步:将JsonWebToken返回为字符串。

payload

payload 必须是一个object, buffer或者string。注意, exp只有当payload是object字面量时才可以设置

如果payload不是buffer或string,它将被强制转换为使用的字符串JSON.stringify()。

secretOrPrivateKey

secretOrPrivateKey 是包含HMAC算法的密钥或RSA和ECDSA的PEM编码私钥的string或buffer。

options

options:

  • algorithm:加密算法(默认值:HS256)
  • expiresIn:过期时间, 以秒表示或描述时间跨度zeit / ms的字符串。如60,"2 days","10h","7d"
  • notBefore:生效时间, 以秒表示或描述时间跨度zeit / ms的字符串。如:60,"2days","10h","7d"
  • audience:受众
  • issuer:签发人
  • jwtid:编号
  • subject:主体
  • noTimestamp
  • header

在expiresIn,notBefore,audience,subject,issuer没有默认值时。也可以直接在payload中用exp,nbf,aud,sub和iss分别表示,但是你不能在这两个地方同时设置。

生成的jwts通常会默认包含一个iat值除非指定了noTimestamp。

jwt.sign({
  exp: Math.floor(Date.now() / 1000) + (60 * 60),
  data: '一个小时过期'
}, 'demo')
// 或者
jwt.sign({
  data: '一个小时过期'
}, 'demo', { expiresIn: '1h' });

jwt.verify(token,secretOrPublicKey,[options,callback])

用法和jwt.sign差不多,用来验证token的合法性

jwt.decode(token [,options])

返回解码没有验证签名是否有效的payload, 用来获取payload

参考链接:JSON Web Token 入门教程,
jsonwebtoken文档, jwt.io,github: node-jsonwebtoken

你可能感兴趣的:(jwt介绍,以及在node和koa中的应用)