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中array.reduce()数组方法的四种使用实例

    当我们使用JavaScript处理数组时,reduce()是一个非常有用的方法。reduce()方法允许我们通过迭代数组中的每个元素,并将它们组合成单个值来加工整个数组。下面详细来讲解如何使用reduce()方法,其中包括四种使用实例,每种用法都有一条示例。 1. 计算数组中所有元素的总和 const numbers = [1, 2, 3, 4, 5]; c…

    JavaScript 2023年5月27日
    00
  • JS判断数组是否包含某元素实现方法汇总

    首先,判断数组是否包含某一元素是JavaScript中非常基本的操作之一。在这里我们将介绍几种实现方法并提供示例说明。 1. 方法一:使用indexOf函数 使用indexOf函数是判断数组是否包含某元素的简便方法之一。该函数会返回元素在数组中的下标,如果元素不在数组中则返回-1。因此只需判断indexOf函数的返回值是否为-1即可得知元素是否在数组中。 下…

    JavaScript 2023年5月27日
    00
  • javascript 兼容所有浏览器的DOM扩展功能

    要兼容所有浏览器的DOM扩展功能,我们需要为每个浏览器提供相应的代码,以确保我们的JavaScript代码在所有浏览器中运行成功。以下是一些我们可以使用的方法: 使用polyfill:Polyfill是一种JavaScript代码,它提供了在旧版本浏览器中缺少的新API和语言特性的兼容性。我们可以使用polyfill来让旧版本的浏览器来支持新的DOM扩展。比…

    JavaScript 2023年6月10日
    00
  • javascript for-in有序遍历json数据并探讨各个浏览器差异

    JavaScript for-in 有序遍历 JSON 数据并探讨各个浏览器差异 什么是JavaScript for-in? JavaScript for-in 语句循环遍历对象的属性。语句还会遍历可枚举的属性,其中不仅包括对象自己的属性,还包括从它的原型继承的属性。 如何使用JavaScript for-in有序遍历JSON数据? 在 JavaScript…

    JavaScript 2023年5月27日
    00
  • Javascript中判断变量是数组还是对象(array还是object)

    如果要判断一个变量是否为数组或对象,可以使用JavaScript中的typeof运算符和Array.isArray()方法。下面详细讲解JavaScript中判断变量是数组还是对象的攻略。 使用typeof运算符 使用typeof运算符判断变量类型 使用typeof运算符可以返回一个字符串,表示变量类型。如果变量是数组,返回的类型为object,如果变量是对…

    JavaScript 2023年5月27日
    00
  • Javascript 原型与原型链深入详解

    Javascript 原型与原型链深入详解 原型 在JavaScript中,每一个对象都有一个指向其原型的属性,称之为 __proto__,原型本身也是一个对象。在Javascript中使用函数构造对象时,函数本身也有一个原型属性,称之为 prototype。我们可以使用 Object.getPrototypeOf() 方法实现查找一个对象的原型。比如: l…

    JavaScript 2023年6月10日
    00
  • JSP和Struts解决用户退出问题

    当用户想要退出系统时,我们需要清除用户的登录状态,以保证安全性和私密性。在JSP和Struts中,都提供了比较简便的实现方式。 JSP解决用户退出问题 在JSP中,我们可以通过Session对象来保存用户登录状态。因此,当用户想要退出系统时,我们只需要清除Session对象,就可以实现该功能。 示例代码: <% session.removeAttrib…

    JavaScript 2023年6月11日
    00
  • 如何进行微信公众号开发的本地调试的方法

    如何进行微信公众号开发的本地调试 微信公众号开发的本地调试可以帮助开发人员在本地环境中快速进行代码调试和测试,从而加快开发效率。下面是进行微信公众号开发的本地调试的具体步骤。 步骤一:创建微信公众号开发者账号 首先需要在微信公众平台上注册一个开发者账号。注册成功后,可以创建一个微信公众号并获取到开发者ID和开发者密钥。 步骤二:下载安装微信公众号调试工具 可…

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