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日

相关文章

  • 新手入门js闭包学习过程解析

    新手入门JS闭包学习过程解析 JS闭包是JS中一个非常重要且常见的概念,但它的概念对于初学者来说可能会比较难理解和掌握。本文将详细讲解新手如何入门JS闭包,并提供相关示例进行说明。 什么是JS闭包 JS闭包(Closure)是指有权访问另一个函数作用域中变量的函数,即在函数内部创建一个可以访问外部变量的作用域。它是指那些能够访问自由变量的函数,即使在这些函数…

    JavaScript 2023年6月10日
    00
  • vue $router和$route的区别详解

    下面是详细讲解“vue $router和$route的区别详解”的完整攻略: 背景 Vue.js 是一个轻量级的 MVVM 前端框架,常用的路由管理器是 vue-router。在使用 vue-router 过程中,可能会涉及到两个关键对象:$router 和 $route。这两个对象貌似很相似,但实际上有着明确的区别。本文将详细讲解两者的区别和应用场景。 $…

    JavaScript 2023年6月11日
    00
  • 浅谈JavaScript宏任务和微任务执行顺序

    浅谈JavaScript宏任务和微任务执行顺序 在 JavaScript 中,任务被分为 宏任务(macrotask)和 微任务(microtask)。而在 JavaScript 中,事件循环(event loop)来负责管理和执行这些任务。 宏任务(macrotask) 宏任务是 JavaScript 中较为常见的任务类型,包括以下几种: 脚本本身; 用户…

    JavaScript 2023年6月11日
    00
  • 微信小程序 如何保持登录状态

    关于如何保持微信小程序登录状态,一般有两种方法: 1. 使用微信原生的登录态 我们可以调用登录 API 获取微信官方提供的登录态码(即 login code),然后将该码发送给自己的服务器进行验证和登录。服务器完成登录后,会返回一个 session key,该 key 应该在每次请求需要登录态的接口时携带,并在客户端进行本地存储,以便下次使用。 具体实现流程…

    JavaScript 2023年6月11日
    00
  • el-form-item prop属性动态绑定不生效问题及解决

    下面是“el-form-item prop属性动态绑定不生效问题及解决”的完整攻略: 问题描述 在Vue.js的Element UI框架中,使用el-form-item组件时,有时即便将组件的prop属性动态绑定到数据对象上,但修改数据对象时却没有触发组件的重新渲染,导致绑定失效。 例如,如下代码中的el-form-item组件,虽然将其prop属性disa…

    JavaScript 2023年6月10日
    00
  • JavaScript数据类型

    JavaScript 是一种弱类型语言,它的数据类型包括基本数据类型和引用数据类型,下面就分别对它们进行详细讲解: 基本数据类型 JavaScript 的基本数据类型包括:数字、字符串、布尔值、undefined 和 null。 数字 数字可以是整数或者小数,例如: var num1 = 10; // 整数 var num2 = 3.14; // 小数 字符…

    Web开发基础 2023年3月30日
    00
  • 解析JavaScript中的字符串类型与字符编码支持

    解析JavaScript中的字符串类型与字符编码支持 在JavaScript中,字符串类型是一种非常基础的数据类型,通常由一些字符组成。本攻略将详细讲解JavaScript中的字符串类型以及字符编码支持。 字符定义 在JavaScript中,一个字符是指一个单一的字符,可以是字母、数字、符号等等,每个字符都有用于表示它的唯一二进制数字编码。在ASCII(Am…

    JavaScript 2023年5月18日
    00
  • js判断当前页面用什么浏览器打开的方法

    判断当前页面使用的浏览器主要有两种方式:一种是通过navigator对象,一种是通过检测浏览器特有的全局变量。 通过navigator对象 在浏览器中,可以通过navigator对象获取关于浏览器的一些信息,包括浏览器名称、版本信息和操作系统等。通过判断浏览器名称和版本信息,我们可以判断当前页面使用的浏览器。 以下是示例代码: // 判断浏览器是否为IE i…

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