Nuxt3 server api 实现jwt登录接口,token签发&校验

作者: tww844475003 分类: 前端开发 发布时间: 2024-12-09 23:29

Nuxt3 是什么?

Nuxt 3是一个基于Vue 3的服务器端渲染(SSR)框架,它继承了Nuxt.js的核心概念,并利用Vue 3的最新特性,如组合式API(Composition API)和<script setup>语法,来提供更加现代化的开发体验。以下是Nuxt 3的一些关键特性:

  1. 性能优化:Nuxt 3在性能方面做了很多优化,例如服务器端渲染(SSR)、预渲染(prerendering)等,这些都有助于提高应用程序的加载速度和运行效率。
  2. 模块化:Nuxt 3是基于Vue.js的模块化架构,这意味着你可以将应用程序分解为多个独立的模块,从而更好地组织和管理代码。
  3. 自动化:Nuxt 3提供了许多内置的功能,如自动化代码生成、热重载、单元测试等,这些功能可以帮助你更快速地开发和调试应用程序。
  4. 支持所有渲染模式:Nuxt.js可以自己选择浏览器还是服务器渲染模式。在服务端渲染的SSR,在客户端渲染的CSR,以及一个静态的SSG,Nuxt.js可以用一套代码生产多类型环境,而且模式的切换也非常简单。
  5. 基于Vue 3的高性能开发:Nuxt 3全面拥抱Vue 3,Vue 3不仅引入了类似React Hooks的Composition API以及一些TypeScript支持,同时提升了性能,减小了bundle size。
  6. 高度集成Vite、Vue Router等实用库:Nuxt 3集成了Vite、Vue Router等实用库,提供了更快的构建速度和更好的开发体验。
  7. 更轻、更快:服务器部署缩小至75倍以及针对现代浏览器的较小的客户捆绑包,优化了冷启动与动态服务器代码拆分,由nitro提供。
  8. 混合型渲染:现在可以实现增量静态生成和其他高级模式。
  9. Suspense:在导航之前或之后,在任何组件中获取数据。
  10. 组合式API:使用Composition API和Nuxt 3的composables来实现真正的代码可重用性。
  11. Nuxt CLI:全新的零依赖性体验,方便脚手架和模块集成。
  12. Nuxt 开发工具:在浏览器中直接使用信息和快速修复,工作更快。
  13. Nuxt Kit:全新的模块开发,采用TypeScript以及跨版本兼容性。
  14. webpack 5:构建时间更快,捆绑尺寸更小,不需要配置。
  15. Vite:通过使用Vite作为您的捆绑器,体验闪电般的HMR速度。
  16. TypeScript:使用本地TypeScript和ESM构建 – 不需要额外的步骤。

Nuxt 3是一个开源的框架,使Web开发变得简单而强大,帮助开发者构建高性能的单页应用程序(SPA),并提供完整的开发、生产、热更新和预渲染功能。

如何实现 jwt token签发&校验

开发一个网页端的项目,必不可少的功能莫过于系统登录,非常普遍。下面我们来实现一个简单的登录token签发&校验接口

这里我们准备采用 nuxt3、prisma、mysql等实现,这些环境搭建请看扩展阅读的文档。官方文档写得都非常清楚。

  • 实现一个prisma数据模型
model User {
  id    Int    @id @default(autoincrement())
  userName String @unique
  password String
}
  • 实现登录接口

prisma实例

import { PrismaClient } from "@prisma/client";

const prismaClientSingleton = () => {
  return new PrismaClient({
    omit: {
      sys_user: {
        password: true // 全局屏蔽 password 字段返回
      }
    }
  });
};

type PrismaClientSingleton = ReturnType<typeof prismaClientSingleton>;

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClientSingleton | undefined;
};

const prisma = globalForPrisma.prisma || prismaClientSingleton();

export default prisma;

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

密码数据保存,一般都会加密存储,这里采用 crypto-js 模块 做 MD5 加密。

import CryptoJS from 'crypto-js';

const MD5_KEY = 'ifrontend.net';

export const encryptAES = (value: string) => {
  if (value == '') return '';
  const keyHex = CryptoJS.enc.Utf8.parse(MD5_KEY);
  const encrypted = CryptoJS.AES.encrypt(value, keyHex, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7,
  });
  return encrypted.toString();
}

jwt 签发&校验,这里采用的是 jsonwebtoken

import jwt from 'jsonwebtoken';

const secretKey = 'ifrontend.net';

export const signToken = (username: string, expiresIn: string = '1h') => {
  return jwt.sign({ username }, secretKey, { expiresIn });
}

export const verifyToken = (token: string) => {
  try {
    const decoded = jwt.verify(token, secretKey);
    return decoded;
  } catch (err) {
    return null;
  }
}

注意:token失效时间,expiresIn,支持时间格式 "2 days""10h""7d"

expiresIn:以秒或描述时间跨度vercel/ms的字符串表示。
例如:60,“2天”,“10小时”,“7天”。数值被解释为秒数。如果使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位(“120”等于“120ms”)。

import prisma from '@/server/lib/prisma';
import { encryptAES } from '@/server/lib/md5';
import { signToken } from '@/server/lib/jwt';

export default defineEventHandler(async (event) => {
  try {
    const body = await readBody(event);
    const { userName, password } = body;

    const user = await prisma.User.findMany({
      where: {
        userName,
        password: encryptAES(password),
      },
    });

    if (!user) {
      return {
        code: 200,
        msg: '用户名或者密码有误',
      };
    } else {
      return {
        code: 200,
        msg: '登录成功',
        data: signToken(userName),
      }
    }
  } catch (error) {
    throw error;
  } finally {
    await prisma.$disconnect(); // 关闭连接
  }
})

看着代码其实也不多,比较简单。也好像实现完成了,是的,非常简单。登录接口完全实现了,但是还有比较重要的一步,如果拦截住其它接口服务,必须登录获取了token才有权限访问,无token或者token失效,无法阴访问服务。

jwt token 校验

这里就要用到 Nuxt3 server 的接口中间件能力

Nuxt 将自动读取 ~/server/middleware 中的任何文件以创建您的项目的服务器中间件。

中间件处理程序将在任何其他服务器路由之前运行每个请求,以添加或检查标头、记录请求或扩展事件请求对象。

// auth.ts

import { verifyToken } from '@/server/lib/jwt';

export default defineEventHandler((event) => {
  // 无需校验的token权限的服务
  const notAuthUrls = [
    '/api/user/login',
  ];
  const currentUrl = event.node.req.url;
  
  if (!notAuthUrls.includes(currentUrl as string)) {
    // 获取headers
    const headers = getHeaders(event);
    const authorization = headers['authorization'] as string;
    if (authorization) {
      const token = authorization.split(' ')[1];
      if (!verifyToken(token)) {
        return {
          code: 403,
          msg: '登录失效'
        }
      }
    } else {
      return {
        code: 404,
        msg: '无权限'
      }
    }
  }
})

扩展阅读

Nuxt3中文网

prisma中文网

crypto-js

jsonwebtoken

前端开发那点事
微信公众号搜索“前端开发那点事”

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注