经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Node.js » 查看文章
Node.js 使用 express-jwt 解析 JWT
来源:cnblogs  作者:zkqiang  时间:2019/11/7 20:41:53  对本文有异议

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

关于 JWT

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

它通常是这个样子:

  1. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

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

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

关于 express-jwt

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

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

开始使用

安装

  1. npm install express-jwt

加入中间件

  1. const expressJWT = require('express-jwt')
  2. app.use(expressJWT({
  3. secret: 'secret12345' // 签名的密钥 或 PublicKey
  4. }).unless({
  5. path: ['/login', '/signup'] // 指定路径不经过 Token 解析
  6. }))

生成 Token

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

  1. const jwt = require('jsonwebtoken')
  2. app.post('/login', function (req, res) {
  3. // 注意默认情况 Token 必须以 Bearer+空格 开头
  4. const token = 'Bearer ' + jwt.sign(
  5. {
  6. _id: user._id,
  7. admin: user.role === 'admin'
  8. },
  9. 'secret12345',
  10. {
  11. expiresIn: 3600 * 24 * 3
  12. }
  13. )
  14. res.json({
  15. status: 'ok',
  16. data: { token: token }
  17. })
  18. })

获取解析内容

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

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

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

  1. {
  2. _id: '5dbbc7daaf7dfe003680ba39',
  3. admin: true,
  4. iat: 1572587484,
  5. exp: 1573192284
  6. }

解析失败

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

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

修改结果字段

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

  1. app.use(jwt({
  2. secret: 'secret12345',
  3. requestProperty: 'auth'
  4. }))

允许无 Token 请求

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

  1. app.use(jwt({
  2. secret: 'secret12345',
  3. credentialsRequired: false
  4. }))

自定义解析

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

  1. app.use(jwt({
  2. secret: 'secret12345',
  3. credentialsRequired: false,
  4. getToken: function fromHeaderOrQuerystring (req) {
  5. if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
  6. return req.headers.authorization.split(' ')[1]
  7. } else if (req.query && req.query.token) {
  8. return req.query.token
  9. }
  10. return null
  11. }
  12. }))

吊销 Token

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

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

  1. const jwt = require('express-jwt')
  2. const blacklist = require('./blacklist')
  3. let isRevokedCallback = function(req, payload, done){
  4. let issuer = payload.iss
  5. let tokenId = payload.jti
  6. blacklist.getRevokedToken(issuer, tokenId, function(err, token){
  7. if (err) { return done(err) }
  8. return done(null, !!token) // 第二个参数为 true 则不通过
  9. })
  10. }
  11. app.use(jwt({
  12. secret: 'secret12345',
  13. isRevoked: isRevokedCallback
  14. }))

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


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

原文链接:http://www.cnblogs.com/zkqiang/p/11810203.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号