koa+jwt实现token验证与刷新功能

接下来我会详细讲解如何使用koa和jwt实现token验证与刷新功能,这个过程包括以下几步:

  1. 安装koa和jsonwebtoken模块:
npm install koa jsonwebtoken
  1. 初始化koa应用,配置路由和中间件:
const Koa = require('koa');
const Router = require('koa-router');
const jwt = require('jsonwebtoken');

const app = new Koa();
const router = new Router();

app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.status || 500;
    ctx.body = { message: err.message };
  }
});

router.post('/api/login', async (ctx, next) => {
  // 获取用户名和密码
  const { username, password } = ctx.request.body;

  // 检查用户名和密码是否正确
  if (username === 'admin' && password === '123456') {
    // 生成 token
    const token = jwt.sign({ username }, 'my_secret');

    // 把 token 发送给客户端
    ctx.body = { token };
  } else {
    // 如果用户名或密码不正确,返回 401 错误
    ctx.throw(401, '用户名或密码不正确');
  }
});

router.get('/api/user', async (ctx, next) => {
  // 从请求头中获取 token
  const token = ctx.header.token;

  try {
    // 验证 token 是否正确
    const decoded = jwt.verify(token, 'my_secret');
    // 如果验证通过,返回用户信息
    ctx.body = { username: decoded.username };
  } catch (err) {
    // 如果验证不通过,返回 401 错误
    ctx.throw(401, 'token 失效,请重新登录');
  }
});

app.use(router.routes());
app.use(router.allowedMethods());

const port = 3000;
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

在上面的代码中,我们定义了两个路由,一个是登录接口/api/login,一个是获取用户信息接口/api/user。在登录接口中,如果用户名和密码验证通过,就会生成一个包含用户名的 token,并把它发送给客户端;在获取用户信息接口中,会先从请求头中获取 token,然后验证它是否正确,如果验证通过,就返回用户信息。

  1. 测试接口是否正常工作

我们可以使用 Postman 等工具来测试接口是否正常工作。首先,我们需要向 /api/login 发送一个 POST 请求,包含用户名和密码:

POST http://localhost:3000/api/login
Content-Type: application/json

{
  "username": "admin",
  "password": "123456"
}

如果用户名和密码验证通过,服务器会返回包含 token 的 JSON 数据:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjM5MzE5Nzg0LCJleHAiOjE2MzkzMTk3OTZ9.wuVwQSZyew3D8R-6YoX_q5xO5QsZUhGwYV37oy1oxoE"
}

我们可以把这个 token 复制下来,然后在请求头中加入 token 字段,向 /api/user 发送GET请求:

GET http://localhost:3000/api/user
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjM5MzE5Nzg0LCJleHAiOjE2MzkzMTk3OTZ9.wuVwQSZyew3D8R-6YoX_q5xO5QsZUhGwYV37oy1oxoE

如果 token 验证通过,服务器会返回当前用户的用户名:

{
  "username": "admin"
}

这说明我们已经成功实现了使用koa和jwt实现token验证与刷新功能。

示例1:使用token实现用户身份认证

在实际项目中,我们需要保护某些只有登录用户才能访问的资源或接口。在这种情况下,我们可以在路由中使用中间件来验证token是否正确。例如:

function authMiddleware(ctx, next) {
  const token = ctx.header.token;

  try {
    const decoded = jwt.verify(token, 'my_secret');
    ctx.state.username = decoded.username;
    return next();
  } catch (err) {
    ctx.throw(401, 'token 失效,请重新登录');
  }
}

router.get('/api/posts', authMiddleware, async (ctx, next) => {
  // 根据用户查找文章列表
  const posts = await findPostsByUsername(ctx.state.username);
  ctx.body = { posts };
});

在上面的代码中,我们定义了一个authMiddleware中间件来验证token是否正确。如果验证通过,就把用户名存储在ctx.state对象中,然后调用next()方法放行;否则,就返回401错误。在路由中,我们把这个中间件作为第二个参数传递进去,表示需要对/api/posts这个路由进行身份验证。如果通过身份验证,就会返回该用户的文章列表。

示例2:使用refresh token实现token自动刷新

在实际项目中,token有时效性。如果用户长时间不操作,在token失效前,token不可用。这时候,我们可以使用refresh token,自动刷新token,延长token的有效期。示例如下:

const refreshTokens = {}; // 用于存储refresh token

router.post('/api/login', async (ctx, next) => {
  const { username, password } = ctx.request.body;
  // 检查用户名和密码是否正确
  if (checkPassword(username, password)) {
    // 生成 token 和 refresh token,并且将 refresh token 存储到服务端内存中
    const token = jwt.sign({ username }, 'my_secret', { expiresIn: '1h' });
    const refreshToken = jwt.sign({ username }, 'my_secret_refresh', { expiresIn: '2h' });
    refreshTokens[refreshToken] = username;

    // 返回 token 和 refresh token
    ctx.body = { token, refreshToken };
  } else {
    ctx.throw(401, '用户名或密码不正确');
  }
});

router.post('/api/refresh-token', async (ctx, next) => {
  const { refreshToken } = ctx.request.body;

  try {
    // 验证 refresh token 是否正确
    const decoded = jwt.verify(refreshToken, 'my_secret_refresh');

    // 如果验证通过,生成新的 token,并将它发送给客户端
    const username = refreshTokens[refreshToken];
    const token = jwt.sign({ username }, 'my_secret', { expiresIn: '1h' });
    ctx.body = { token };
  } catch (err) {
    // 如果验证不通过,返回 400 错误
    ctx.throw(400, 'invalid refresh token');
  }
});

在上面的代码中,我们在登录接口中生成了一个refreshToken,并将它存储到一个对象中。如果用户需要刷新token,就需要向/api/refresh-token发送一个POST请求,包含refreshToken:

POST http://localhost:3000/api/refresh-token
Content-Type: application/json

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjM5MzIwMzE2LCJleHAiOjE2MzkzNDg3MTZ9.zA1AJIv_3OoIUpniJAhYaMz0LNtXH665NDDmIe9BN9s"
}

如果refreshToken验证通过,服务器会生成一个新的token,并返回给客户端:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjM5MzIwNDM3LCJleHAiOjE2MzkzMjQwMzd9.KAapczYIfNw_9g6KXlc8GAPRA_UAjd2dQHSElid6-EU"
}

这样做的好处是,即使token过期,在refreshToken仍然有效的情况下,客户端仍然可以通过向服务器请求新的token来继续访问需要登录才能访问的资源,从而提高了用户体验。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:koa+jwt实现token验证与刷新功能 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • 魔方在线秒表javascript版

    魔方在线秒表是一款基于JavaScript开发的网页应用,主要用于计时比赛、训练等场景。下面将为大家详细讲解该应用的完整攻略。 安装与运行 下载代码 从GitHub上下载代码:https://github.com/AlgerHwang/Rubik-s-Cube-Online-Stopwatch,或者通过Git命令克隆仓库: git clone https:/…

    JavaScript 2023年5月27日
    00
  • 微信小程序 倒计时组件实现代码

    下面就来分享微信小程序中倒计时组件的实现过程吧。 准备工作 在开始具体讲解之前,需要对微信小程序的基础知识有一定的了解,包括:- 小程序的目录结构- WXML、WXSS、JS、JSON 文件的作用- 小程序的基础组件和事件绑定等操作 倒计时组件实现步骤 1. 创建小程序项目 首先,在微信开发者工具中创建一个基础的小程序项目。 2. 创建倒计时组件 在项目中创…

    JavaScript 2023年6月11日
    00
  • JavaScript数组合并的8种常见方法小结

    以下是对“JavaScript数组合并的8种常见方法小结”的完整攻略: 1. concat()方法 定义:concat()方法用于连接两个或多个数组。该方法并不会改变原数组,而是返回一个新的数组,包含所有被连接的数组的元素。 语法:arr.concat(array1, array2, …, arrayX) 示例: const arr1 = [1, 2, …

    JavaScript 2023年5月27日
    00
  • js判断一个字符串是否包含一个子串的方法

    要判断一个字符串是否包含一个子串,可以使用JavaScript中的indexOf()方法或者includes()方法。 使用indexOf()方法 indexOf()方法可以在一个字符串中查找给定的子串,如果找到了则返回该子串第一次出现的位置,如果没有找到则返回-1。因此,我们可以根据该方法返回的结果来判断该子串是否包含在目标字符串中。 代码示例: let …

    JavaScript 2023年5月28日
    00
  • js调试系列 初识控制台

    JS调试系列——初识控制台 什么是控制台 控制台是浏览器提供的调试工具,可以用来查看JavaScript代码的运行情况,如代码执行顺序,变量的值等。控制台可以输出信息,查看调用堆栈,进行代码地图等操作。Chrome浏览器的控制台是最为强大的。 打开控制台 在Chrome浏览器中,可以通过快捷键 Ctrl + Shift + J 打开控制台。也可以右键页面空白…

    JavaScript 2023年5月27日
    00
  • JavaScript 字符串与数组转换函数[不用split与join]

    下面是“JavaScript 字符串与数组转换函数[不用split与join]”的完整攻略。 为什么不用split和join 在讲解字符串与数组转换函数之前,我们先来谈谈为什么要不用split和join。split和join是JavaScript中常用的字符串与数组转换函数,但是在某些场景下,特别是在大数据量时,使用这两个函数会影响效率,因此需要考虑其他的转…

    JavaScript 2023年5月28日
    00
  • Javascript Math cos() 方法

    JavaScript中的Math.cos()方法用于返回一个数的余弦值。该方法接受一个参数,即要计算余弦值的角度,单位为弧度。以下是关于Math.cos()方法的完整攻略,包括两个示例。 JavaScript Math对象的cos()方法 JavaScript Math对象中的cos()方法用于返回一个数的余弦值。该方法接受一个参数,即要计算余弦值的角度,单…

    JavaScript 2023年5月11日
    00
  • js实现具有高亮显示效果的多级菜单代码

    实现具有高亮显示效果的多级菜单代码需要以下步骤: 1.准备HTML结构 首先,需要准备一个基本的HTML结构。我们可以使用无序列表(ul)和有序列表(ol)来构建多级菜单。例如,下面是一个三级菜单结构: <ul> <li><a href="#">一级菜单</a> <ul> &lt…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部