Node.js 上 Token 鉴权常用的是 passport,它可以自定义校验策略,但如果你是用 express 框架,又只是解析 JWT 这种简单需求,可以尝试下 express-jwt 这个中间件。

关于 JWT

JWT 全称 JSON Web Token,是代替传统 session 认证的解决方案。其原理是服务端生成一个包含用户唯一标识的 JSON 对象,颁发给客户端。客户端请求需要权限的接口时,只要把这个 JSON 再原样发回给服务端,服务器通过解析就可识别用户。

它通常是这个样子:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

这个 JSON 对象通过 . 分成三段,包含了请求头(加密算法)、负载信息(如 userId、过期时间),还有通过服务端密钥生成的签名来保证不被篡改。

这种机制使服务端不再需要存储 Token,因此是非常轻量的用户认证方案。并且对于微服务这种需要不同服务间共用 Token 的跨域认证,JWT 是目前的首选。

关于 express-jwt

express-jwt 是 Node.js 的一个开源库,由 ID 认证服务提供商 auth0 开发,是专用于 express 框架下解析 JWT 的中间件。

它使用非常简单,而且会自动把 JWT 的 payload 部分赋值于 req.user,方便逻辑部分调用。

开始使用

安装

npm install express-jwt

加入中间件

const expressJwt = require('express-jwt')

app.use(expressJwt({
secret: 'secret12345' // 签名的密钥 或 PublicKey
}).unless({
path: ['/login', '/signup'] // 指定路径不经过 Token 解析
}))

生成 Token

生成 Token 的方式依然使用 jsonwebtoken,比如将下列代码加入到登录接口的返回部分:

const jwt = require('jsonwebtoken')

app.post('/login', function (req, res) {
// 注意默认情况 Token 必须以 Bearer+空格 开头
const token = 'Bearer ' + jwt.sign(
{
_id: user._id,
admin: user.role === 'admin'
},
'secret12345',
{
expiresIn: 3600 * 24 * 3
}
)
res.json({
status: 'ok',
data: { token: token }
})
})

获取解析内容

当收到带 Token 的请求,如果解析成功,就可以在路由回调里通过 req.user 来访问:

app.get('/protected', function (req, res) {
if (!req.user.admin)
return res.sendStatus(401)
res.sendStatus(200)
})

req.user 实际就是 JWT 的 payload 部分:

{
_id: '5dbbc7daaf7dfe003680ba39',
admin: true,
iat: 1572587484,
exp: 1573192284
}

解析失败

如果解析失败,会抛出 UnauthorizedError,可以通过后置中间件来捕获:

app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
res.status(401).send('invalid token')
}
})

修改结果字段

默认解析结果会赋值在 req.user,也可以通过 requestProperty 来修改:

app.use(expressJwt({
secret: 'secret12345',
requestProperty: 'auth'
}))

允许无 Token 请求

当接口允许不带 Token 和带 Token 两种状态的访问时(比如文章详情登录后判断点赞),可以通过 credentialsRequired: false 来对无 Token 请求不进行解析和抛出异常。

app.use(expressJwt({
secret: 'secret12345',
credentialsRequired: false
}))

自定义解析

默认情况下,express-jwt 是从请求 Headers 的 Authorization 字段来获取 Token 并解析。

通过 getToken 也可以自定义一些解析逻辑,比如使用其他 Header 字段,自定义抛出异常等:

app.use(expressJwt({
secret: 'secret12345',
credentialsRequired: false,
getToken: function fromHeaderOrQuerystring (req) {
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
return req.headers.authorization.split(' ')[1]
} else if (req.query && req.query.token) {
return req.query.token
}
return null
}
}))

作废 Token

在 JWT 机制中,由于 Token 通常不进行存储,如果想作废某一条 Token,一般都是通过被动的方式。

常用的方式是建立某个字段的黑名单(比如 TokenId),对所有 Token 进行过滤,express-jwt 专门提供了回调来处理这种情况:

const expressJwt = require('express-jwt')
const blacklist = require('./blacklist') let isRevokedCallback = function(req, payload, done){
let issuer = payload.iss
let tokenId = payload.jti blacklist.getRevokedToken(issuer, tokenId, function(err, token){
if (err) { return done(err) }
return done(null, !!token) // 第二个参数为 true 则不通过
})
} app.use(expressJwt({
secret: 'secret12345',
isRevoked: isRevokedCallback
}))

更多用法可以查看 官方文档


本文属于原创,首发于微信公众号「面向人生编程」,如需转载请后台留言。

关注后回复以下信息获取更多资源

回复【资料】获取 Python / Java 等学习资源

回复【插件】获取爬虫常用的 Chrome 插件

回复【知乎】获取最新知乎模拟登录

Node.js 使用 express-jwt 解析 JWT的更多相关文章

  1. Node.js基于Express框架搭建一个简单的注册登录Web功能

    这个小应用使用到了node.js  bootstrap  express  以及数据库的操作 :使用mongoose对象模型来操作 mongodb 如果没了解过的可以先去基本了解一下相关概念~ 首先注 ...

  2. node.js,express入门看详细篇

    先最简单的代码 安装 npm install express app.js 代码内容 const express = require('express') const app = express() ...

  3. node.js之express框架

    之前学习过node.js接触过express框架,最近为了编写一个mock server正好用到了express.下面正好就跟大家介绍一下关于express.今天的内容主要围绕这么几个方面? expr ...

  4. 【node.js】Express 框架

    Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具. 使用 Express 可以快速地搭建一个完整功能的网 ...

  5. Code Your First API With Node.js and Express: Set Up the Server

    How to Set Up an Express API Server in Node.js In the previous tutorial, we learned what the REST ar ...

  6. Node.js、express、mongodb 实现分页查询、条件搜索

    前言 在上一篇Node.js.express.mongodb 入门(基于easyui datagrid增删改查) 的基础上实现了分页查询.带条件搜索. 实现效果 1.列表第一页. 2.列表第二页 3. ...

  7. Node.js、express、mongodb 入门(基于easyui datagrid增删改查)

    前言 从在本机(win8.1)环境安装相关环境到做完这个demo大概不到两周时间,刚开始只是在本机安装环境并没有敲个Demo,从周末开始断断续续的想写一个,按照惯性思维就写一个增删改查吧,一方面是体验 ...

  8. node.js和express.js安装和使用步骤 [windows]

    PS: NODEJS:https://nodejs.org NPM:https://www.npmjs.com/ 一.node.js安装与配置 到https://nodejs.org/en/downl ...

  9. node.js框架express的安装

    node.js框架express的安装 首先假定你已经安装了 Node.js,接下来为你的应用创建一个目录,然后进入此目录并将其作为当前工作目录. $ mkdir myapp $ cd myapp 通 ...

  10. Node.js系列-express(上)

    前言 Node.js系列的第一篇:http,大概描述了通过使用node.js内置的api创建一个服务并监听request实现简单的增删改查.现在,我们就通过通读express官网及使用express框 ...

随机推荐

  1. Python IAQ中文版 - Python中少有人回答的问题

    Python中少有人回答的问题 The Python IAQ: Infrequently Answered Questions 1 Q: 什么是"少有人回答的问题(Infrequently ...

  2. __pycache__

    最近在使用python写一个串口模块的时候,偶然发现运行脚本之后,在工程文件夹下面出现了这样一个文件夹__pycache__,所以就特意到网上查了一下这个文件夹是怎么回事. 我们先在源文件中添加一些内 ...

  3. POJ 2533——Longest Ordered Subsequence(DP)

    链接:http://poj.org/problem?id=2533 题解 #include<iostream> using namespace std; ]; //存放数列 ]; //b[ ...

  4. 虚拟机中设置 CentOS 静态 IP

    作为开发人员在工作和学习中通过虚拟机使用 Linux 的情况肯定会非常多,但是 Linux 自带的终端使用体验较差,所以绝大多数使用者都会在宿主机上使用第三方 SSH工具(例如 Xshell)进行连接 ...

  5. 阿里云虚拟主机安装wordpress,提示连接数据库失败的解决方法

      很多新手在购买的虚拟主机后就开始尝试安装,却发现连接数据库老是出错,不知道什么问题,反复检查了自己填写的数据库连接信息发现也没有问题,这个时候我们似乎就没法了. 但这个其实是后台空间的设置问题,你 ...

  6. 防御 DDoS 的终极奥义——又拍云 SCDN

    现如今不论是年轻的 80.90 后,还是 70.60 后,都在享受互联网带来的舒适和便利.在家就可以"逛商场",完全不受时间的限制:在线支付既方便又安全:业余娱乐项目多种多样,打农 ...

  7. Java基础学习笔记(五) - 常用的API

    API介绍 概念:API 即应用编程程序接口.Java API是JDK中提供给我们使用的类说明文档,这些类将底层的代码实现封装.无需关心这些类是如何实现,只需要学习如何使用. 使用:通过API找到需要 ...

  8. nginx(tengine)访问日志分片

    说明 nginx日志按天分片是运维的基本要求,不仅可以减小文件大小,方便检索关键数据,也可以定时删除过期的日志.可是nginx和tengine默认并不支持文件分片,因此需要额外处理. 另外,日志分片需 ...

  9. 分享8点超级有用的Python编程建议

    我们在用Python进行机器学习建模项目的时候,每个人都会有自己的一套项目文件管理的习惯,我自己也有一套方法,是自己曾经踩过的坑总结出来的,现在在这里分享一下给大家,希望多少有些地方可以给大家借鉴.

  10. 第二章Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 一.概述 对与Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每个new操作去写delete/free代码,不容易出现内存泄露和内存溢出问 题, ...