带你一文使用NodeJS、JWT、Vue搞定基于角色的授权

在本教程中 , 我们将完成一个关于如何在 Node.js 中 使用 JavaScript, 并结合 JWT 认证 , 实现基于角色(role based)授权/访问的简单例子 。
作为例子的 API 只有三个路由 , 以演示认证和基于角色的授权:

  • /users/authenticate - 接受 body 中包含用户名密码的 HTTP POST 请求的公开路由 。 若用户名和密码正确 , 则返回一个 JWT 认证令牌
  • /users - 只限于 "Admin" 用户访问的安全路由 , 接受 HTTP GET 请求;如果 HTTP 头部授权字段包含合法的 JWT 令牌 , 且用户在 "Admin" 角色内 , 则返回一个包含所有用户的列表 。 如果没有令牌、令牌非法或角色不符 , 则一个 401 Unauthorized 响应会被返回 。
  • /users/:id - 限于通过认证的任何角色用户访问的安全路由 , 接受 HTTP GET 请求;如果授权成功 , 根据指定的 "id" 参数返回对应用户记录 。 注意 "Admin" 可以访问所有用户记录 , 而其他角色(如 "User")却只能访问其自己的记录 。
教程中的项目可以在 GitHub 上找到:
本地化运行 Node.js 中基于角色的授权 API
  1. 从以上 URL 中下载或 clone 实验项目
  2. 运行 npm install 安装必要依赖
  3. 运行 npm start 启动 API , 成功会看到 Server listening on port 4000
运行 Vue.js 客户端应用除了可以用 Postman 等应用直接测试 API , 也可以运行一个更好的 Vue 项目查看:
  1. 下载 Vue.js 项目代码:
  2. 运行 npm install 安装必要依赖
  3. 为了访问到我们的 Node.js 返回的数据而不是使用 Vue 项目的本地假数据 , 移除或注释掉 /src/index.js 文件中包含 configureFakeBackend 的两行
  4. 运行 npm start 启动应用
Node.js 项目结构
  • _helpers authorize.js error-handler.js role.js
  • users user.service.js users.controller.js
  • config.json
  • server.js
项目由两个主要的子目录组成 。 一个是 “特性目录”(users) , 另一个是 “非特性/共享组件目录”(_helpers) 。
例子中目前只包含一种 users 特性 , 但增加其他特性也可以照猫画虎地按照同一模式组织即可 。
Helpers 目录路径: /_helpers
包含了可被用于多个特性和应用其他部分的代码 , 并且用一个下划线前缀命名以显眼的分组它们 。
角色中间件路径: /_helpers/authorize.js
const expressJwt = require('express-jwt');const { secret } = require('config.json');module.exports = authorize;function authorize(roles = []) {// 规则参数可以是一个简单字符串 (如 Role.User 或 'User')// 也可以是数组 (如 [Role.Admin, Role.User] 或 ['Admin', 'User'])if (typeof roles === 'string') {roles = [roles];}return [// 认证 JWT 令牌 , 并向请求对象附加用户 (req.user)expressJwt({ secret }),// 基于角色授权(req, res, next) => {if (roles.length}// 认证授权都齐活next();}];授权中间件可以被加入任意路由 , 以限制通过认证的某种角色用户的访问 。 如果角色参数留空 , 则对应路由会适用于任何通过验证的用户 。 该中间件稍后会应用在 users/users.controller.js 中 。
authorize() 实际上返回了两个中间件函数 。
其中的第一个(expressJwt({ secret }))通过校验 HTTP 请求图中的 Authorization 来实现认证 。认证成功时 , 一个 user 对象会被附加到 req 对象上 , 前者包含了 JWT 令牌中的数据 , 在本例中也就是会包含用户 id (req.user.sub) 和用户角色 (req.user.role) 。 sub 是 JWT 中的标准属性名 , 代表令牌中项目的 id 。
返回的第二个中间件函数基于用户角色 , 检查通过认证的用户被授权的访问范围 。