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.iogithub: node-jsonwebtoken

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容