【决战Koa之巅-7】使用JWT对路由进行授权

文章介绍了路由授权的重要性,如保护资源,防止未授权访问。接着详细讲解了OAuth2.0授权协议,常用于第三方应用获取用户数据。然后提到了CAS,主要用于单点登录。重点讨论了JWT,包括其特点和结构,以及如何在KOA中使用KOA-JWT进行路由鉴权。最后给出了一个简单的JWT授权示例。
摘要由CSDN通过智能技术生成

我们目前已经实现了路由代码自动格式化,那么让我们来继续学一学路由鉴权。

一、为什么要路由授权?

很显然,一台服务器上的资源不可能对所有人开放;

我们的一个路由,就对应了一种类型的资源。

以下场景:

  • 未登录的人员,不能访问注册会员才能查看的信息;
  • 降低系统压力,仅为授权人员服务;

二、常见授权方式

那么,就趁此机会,让我们来学学现在常见的授权方式都有哪些吧!

2.1 OAuth2.0

比较流行的授权方式,主要是用于授权第三方应用,获取用户数据;

比如你的应用使用微信登录,会提示获取你是否确认授权三方获取用户信息(OPENID、头像)等等,点击允许后就会拿上票据跳转到三方,三方换取到 access_token 后,就能拿到了微信提供的用户信息,官方时序图如下:

image.png

具体可见:微信OAuth2.0对接介绍

PS:大部分应用首次还会让你再输入手机号+短信验证码,做手机号与微信号的绑定。

由于咱们只是了解,更多可见阮老师的OAuth2.0的简单解释

2.2 CAS

CASOAuth2.0 类似,也是做身份验证和授权,但是 CAS 主要用于单点登录( SSO:即登录一次即可访问所有与该系统连接的应用)。
流程图如下:

CAS基础协议.jpg

想必大家也遇到过,使用 A 系统先跳转到统一认证中心,输入完密码后再跳转回 A 系统。就是这样的机制啦。(更往上就是 IAM系统,这里先按住不表)

2.3 JWT

JWTJSON WEB TOKEN,不难理解是以 JSON 格式进行 WEB 认证的 Token

看一下官方介绍:

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用间传输信息的一种方式。

具有无状态、有效避免 CSRF 攻击、使用移动端、单点登录友好等特点。

通常,JWT 多用于跨域认证和授权,也是一种比较简单的机制。

由三部分构成:

image.png

  • Header:元数据,定义生成签名算法及Token类型;
  • Payload:存放需要传递的数据;
  • Signature:服务器使用 Payload + Header + Secret 通过 Header 中指定的算法生成。

一般形如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZlbmd5cyIsImlhdCI6MTY4NDMwMjk0MSwiZXhwIjoxNjg0Mzg5MzQxfQ.n7DZdoTSW6O0wD0VclFIE0MEwK1tkyTiXSUeX4ZkgFI

OK,let’s do it!

三、整体流程

3.1 接口区分

首先,我们需要对路由进行区分,哪些是开放路由,哪些是需要鉴权成功(输入用户名密码)后获取 JWT,请求头中带上才能使用的路由。

也就是分为两种角色:

  1. 无需登录使用;(游客)
  2. 需要登录后使用;(已登录用户)

3.2 流程图

未命名文件.jpg

四、使用 KOA-JWT

该组件就是一个在 KOA 中的 JWT 中间件。

4.1 安装

npm install koa-jwt jsonwebtoken
  • koa-jwt:对路由进行拦截判断
  • jsonwebtoken:生成 JWT

4.2 使用

关键代码

const jwt = require("koa-jwt");

// 类似于加 salt,需要传递一个密钥串
const JWT_SECRET = "shared-secret"
// 生成 JWT
jwt.sign({ id: uId }, JWT_SECRET, { expiresIn: 24 * 60 * 60 })
/.../
// 给路由加上了 `JWT` 校验,使用 `unless` 去排查不需要校验的路由
app.use(jwt({ secret: JWT_SECRET }).unless({ path: [/^\/auth/] }));

然后,我们来设计一个 auth 接口,用于获取认证信息,当用户名密码输入正确(暂未涉及数据库,用固定参数)后才返回;

设计一个 user 接口,用户返回用户信息,该接口需要授权成功后才能访问,否则就报未授权错误。
完整如下:

const koa = require("koa");
const Router = require("@koa/router");
const jwt = require("jsonwebtoken");
const koaJWT = require("koa-jwt");
const { koaBody } = require("koa-body");
const app = new koa();
const router = new Router();
const JWT_SECRET = "shared-secret";
/**
 * 授权接口,用户名密码正确返回 JWT ,错误则提示
 */
router.post("/auth", async (ctx, next) => {
  const jwtString = jwt.sign({ id: "root" }, JWT_SECRET, {
    expiresIn: 24 * 60 * 60
  });
  const { uId, password } = ctx.request.body;
  if (uId === "root" && password === "123456") {
    ctx.body = { code: "200", msg: "success", token: jwtString };
  } else {
    ctx.body = { code: "-1", msg: "The user name or password is incorrect" };
  }
});

/**
 * 获取用户信息接口,需携带 JWT 访问
 */
router.get("/user", async (ctx, next) => {
  ctx.body = "This is user info.";
});

app.use(koaBody());
app.use(koaJWT({ secret: "shared-secret" }).unless({ path: [/^\/auth/] }));
app.use(router.routes());
app.listen(3000, () => {
  console.log("启动成功!http://localhost:3000");
});

验证:

不携带 JWT 访问未授权接口 localhost:3000/user,提示错误:

image.png

调用localhost:3000/user获取 JWT

密码错误情况:

image.png

正确:

image.png

携带 JWT 访问未授权接口 localhost:3000/user,返回用户信息:

image.png

注意:使用时要在前面增加 Bearer,为什么要这样加?不能不加?就留给大家去探索了!

Demo

JWT-Demo

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值