使用 $fetch 和 Pinia 的 Nuxt 3 JWT 身份验证

2024-02-06

我正在尝试对不同的 API 进行 JWT 身份验证。

由于 @nuxtjs/auth-next 似乎不是最新的,而且据我所知,可以在 Nuxt 3 中使用新的全局方法 fetch 而不是 @nuxtjs/axios (也不是最新的),我认为它自己编写身份验证代码不会太难!但这对我来说仍然是个谜,我只找到了 Vue 项目的文档(使用 Pinia 来保持用户登录),我有点迷失了。

我想实现的目标:

  • 包含电子邮件和密码的登录页面,登录请求发送到 API(编辑:完成!)
  • 从 API 获取 JWT 令牌和用户信息(编辑:完成!)并存储两者(即使页面刷新也保持用户记录)
  • 将 JWT 令牌全局设置为标头 $fetch 请求(?),这样我就不必将其添加到每个请求中
  • 如果用户未登录,则不允许访问其他页面

对此有什么帮助吗?

这是我的 login.vue 页面(之后我必须使用 Vuetify 和 vee-validate,但还是一次一步!)

// pages/login.vue
<script setup lang="ts">
import { useAuthStore } from "~/store/auth";

const authStore = useAuthStore();

interface loginForm {
  email: string;
  password: string;
}

let loginForm: loginForm = {
  email: "",
  password: "",
};

function login() {
  authStore.login(loginForm);
}
</script>

<template>
  <v-container>
    <form @submit.prevent="login">
      <label>E-mail</label>
      <input v-model="loginForm.email" required type="email" />
      <label>Password</label>
      <input v-model="loginForm.password" required type="password" />
      <button type="submit">Login</button>
    </form>
  </v-container>
</template>

目前是 store/auth.ts。

// store/auth.ts
import { defineStore } from 'pinia'
import { encodeURL } from '~~/services/utils/functions'

export const useAuthStore = defineStore({
  id: 'auth,
  state: () => ({
    // TODO Initialize state from local storage to enable user to stay logged in
    user: '',
    token: '',
  })
  actions: {
    async login(loginForm) {
      const URL_ENCODED_FORM = encodeURL({
        email: loginForm.email,
        password: loginForm.password,
      });
      return await $fetch('api_route', {
        headers: {
          "Content-Type": "application/x-www-form-urlencoded"
        },
        method: 'POST',
        body: URL_ENCODED_FORM
      }
    } 
  }
})

为了完整起见,我将分享所有内容,甚至是您标记为已完成的部分。

首先,您需要在后端生成 JWT,您可以在没有任何包的情况下简单地执行此操作,但我建议这个包 https://github.com/auth0/node-jsonwebtoken为了那个原因。另外,我将使用 objection.js 来查询数据库,即使您不知道 objection.js 也应该很容易理解

您的登录视图需要像这样发送登录尝试请求

const token = await $fetch('/api/login', {
    method: 'post',
    body: {
      username: this.username,
      password: this.password,
    },
  });

就我而言,它请求 /server/api/ 中的 login.post.ts

import jwt from 'jsonwebtoken';
import { User } from '../models';

export default defineEventHandler(async (event) => {
  const body = await useBody(event);
  const { id } = await User.query().findOne('username', body.username);
  const token: string = await jwt.sign({ id }, 'mysecrettoken');
  return token;
});

为了简单起见,我在这里没有查询密码,这取决于您如何生成用户密码。 “mysecrettoken”是您的用户永远不应该知道的令牌,因为他们可以像其他人一样登录。当然这个字符串可以是任何你想要的字符串,越长越好。

现在您的用户获得一个令牌作为响应,应该只是一个简单的字符串。我稍后会写一篇关于如何保存这个以供将来请求的文章。

要使用此令牌发出经过身份验证的请求,您将需要执行如下请求:

$fetch('/api/getauthuser', {
            method: 'post',
            headers: {
              authentication: myJsonWebToken,
            },
          });

我更喜欢添加一个中间件来更轻松地访问我的 api 端点中的经过身份验证的用户。该中间件名为 setAuth.ts,位于 server/middleware 文件夹内。它看起来像这样:

import jwt from 'jsonwebtoken';

    export default defineEventHandler(async (event) => {
      if (event.req.headers.authentication) {
        event.context.auth = { id: await jwt.verify(event.req.headers.authentication, 'mysecrettoken').id };
      }
    });

其作用是验证是否传递了身份验证标头,它检查令牌是否有效(使用与您签署 jwt 的相同秘密令牌),如果有效,则将 userId 添加到请求上下文以便于端点访问。

现在,在我的 server/api/getauthuser.ts 端点中可以像这样获取 auth 用户

import { User } from '../models';

export default defineEventHandler(async (event) => {
  return await User.query().findById(event.context.auth.id)
});

由于用户无法设置请求上下文,因此您可以确定您的中间件设置了此 auth.id

您现在已经有了基本的身份验证。

我们生成的令牌具有无限的生命周期,这可能不是一个好主意。如果此令牌暴露给其他人,他们将无限期地拥有您的登录信息,进一步解释将超出此答案的范围。

您可以将身份验证令牌保存在 localStorage 中,以便在下一个页面加载时再次访问它。有些人认为这是一种不好的做法,并且更喜欢使用 cookie 来存储它。我会保持简单并使用 localStorage 。

现在,对于用户不应访问登录以外的页面的部分:我在 middleware/auth.global.ts 中设置了一个全局中间件(您也可以执行一个非全局中间件并为特定页面指定它) auth.global.ts 看起来像这样:

import { useAuthStore } from '../stores';

export default defineNuxtRouteMiddleware(async (to) => {
  const authStore = useAuthStore();

  if (to.name !== 'Login' && !localStorage.getItem('auth-token')) {
    return navigateTo('/login');
  } else if (to.name !== 'Login' && !authStore.user) {
    authStore.setAuthUser(await $fetch('/api/getauthuser', {
      headers: authHeader,
    }));
  }
});

我使用 pinia 将身份验证用户存储在我的 authStore 中,但前提是本地存储中有身份验证令牌 (jwt)。如果有且尚未获取,请通过 getauthuser 端点获取 auth 用户。如果没有 authtoken 并且该页面不是登录页面,则将用户重定向到该页面

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 $fetch 和 Pinia 的 Nuxt 3 JWT 身份验证 的相关文章

  • 让网站登录也能在 WordPress 上使用

    我使用 PHP 和 MySQL 开发了一个网站 该网站已经有登录和注册表单 myweb com 我已经在这个网址添加了 wordpressmyweb com blog 我想禁用 WordPress 上的登录和注册页面并强制用户使用我的 基本
  • 从 Restful 身份验证迁移到 Devise

    许多 Rails 2 3 应用程序正在使用 Restful Authentication 但该插件似乎与 Rails 3 存在一些问题 在升级到 Rails 3 时 我一直在使用 Devise 有什么办法可以顺利地从 Restful Aut
  • Spring Security - 基于令牌的 API 身份验证和用户/密码身份验证

    我正在尝试创建一个主要使用 Spring 提供 REST API 的 Web 应用程序 并尝试配置安全方面 我正在尝试实现这种模式 https developers google com accounts docs MobileApps h
  • 不需要 UserProvider 的自定义身份验证

    我在网上寻找适合我的配置的解决方案 但找不到满足我需求的东西 到目前为止 我已经为此工作了整整三天 但我无法使其正常工作 我确信有几件事我不明白 我正在分支 2 1 上开发我的 symfony 应用程序 为了让这个简短 我有一个网络服务 我
  • 在 JWT Laravel 中使用授权标头时获取 token_not_provided

    I read 本教程 http blog nedex io create an api server for mobile apps using laravel 5 1 我设法使它完美地工作 唯一的问题是当我从 令牌 token here
  • 如果我被冒充,为什么 Win32 API 函数 CredEnumerate() 会返回 ERROR_NOT_FOUND?

    我编写了一些示例代码 当我在普通用户帐户的上下文中从 Windows 命令提示符调用这些代码时 会使用 CredEnumerate 转储所有用户保存的凭据 但是 我真的希望能够从 SYSTEM 用户上下文执行此操作 因此我从 SYSTEM
  • 授予 Rails 应用 API 访问权限的最佳身份验证方法

    我想为我的网络应用程序提供经过身份验证的 API 访问 此类服务的消费者通常是其他网站 服务 验证这些用户身份的最佳方法是什么 OAuth openID http 身份验证 正如我们的工作一样 哪个最好 的答案是这样的 是 这取决于 HTT
  • html 表单发布到 Flex 应用程序

    我有一个基本完成的 Flex 应用程序 它使用 Zend AMF 来连接 提供数据 我的应用程序确实有一个登录屏幕 看起来工作正常 现在我想在我的网站上添加另一个登录表单 允 许用户输入用户名 密码 提交表单时应将数据传递给 Flex 应用
  • IssuerSigningKeyResolver 调用异步方法

    我们使用 IssuerSigningKeyResolver 它是 Microsoft IdentityModel Tokens 的一部分 用于令牌验证并接受非异步委托 我们调用一个异步方法 这将导致阻塞调用 因此想知道使用它的正确方法是什么
  • 在 Postman 中的后续请求中使用身份验证令牌

    我的应用程序 API 需要通过身份验证令牌进行身份验证 简而言之 我们向 authentication端点 它使用包含令牌的 JSON 对象进行响应 例如 token xxxxxxxxxxxxxxxxxxxxxx 我们应用程序中的每个其他
  • 在闪亮的应用程序和多个页面中进行身份验证

    在我正在开发的系统中 我有 3 个不同的参与者 用户 管理员 支持团队 使用 Shiny App 我想知道如何向这三个参与者进行身份验证 每个参与者只能访问他们的页面 我发现使用闪亮的服务器专业版可以实现这一点 但它不是免费的 有什么方法可
  • 瓦廷 Windows 身份验证

    我正在尝试为使用集成身份验证的 Intranet 应用程序编写 Watin 测试 我尝试测试的网页打印 Page User Identity Name 这是我测试的一些代码 if Win32 LogonUser u UserName u D
  • 使用 Cypress 绕过 UI 登录

    我在绕过 UI 登录时遇到问题 我的 Web 应用程序不使用 API 来验证用户身份 没有像这样的端点 login index php只需打开登录页面并提交表单即可登录 应用程序通过以下方式对用户进行身份验证auth REQUEST use
  • DMARC/SPF/DKIM 未使用第三方邮件进行身份验证

    我们最近为我们的域实施了 DMARC 记录 v DMARC1 p 隔离 pct 100 rua mailto 电子邮件受保护 cdn cgi l email protection 隔离 100 未经身份验证的电子邮件并将汇总报告发送给 我
  • Apollo 客户端“未找到命名导出‘删除’”

    我正在尝试创建一个apollo client插件Nuxt 3应用 它当前抛出有关名为的包的错误ts invariant file Users my name Repositories project node modules apollo
  • 如何使用 keycloak 强制每个客户端登录(最佳实践?)

    我们目前正在实施 keycloak 但我们面临着一个问题 我们不确定解决它的最佳方法是什么 我们有不同的网络应用程序使用单点登录 并且运行良好 我们遇到的问题是 当我们在一个 Web 应用程序中使用 sso 登录 然后在另一个 Web 应用
  • 在浏览器上验证 JWT

    我一直在读关于JWT https jwt io 我知道它分为三个部分 即header payload and signature 我将哈希算法保留在标头中 将基本信息保留在有效负载中例如 姓名 年龄 职务 有效期等在有效负载中 然后这两个都
  • 将 gsutil 与谷歌驱动器(不是谷歌云存储)一起使用

    gsutil https cloud google com storage docs gsutil csw 1 gettingstarted use 博托配置文件 https cloud google com storage docs gs
  • 使用单个查询和每用户密码盐进行用户登录

    我决定使用存储在数据库中的每用户盐来实现用户登录 盐作为密码的前缀 该密码使用 SHA 进行哈希处理并存储在数据库中 过去 当我不使用盐时 我会使用典型的方法 使用用户输入的用户名和密码来计算查询返回的行数 然而 对于每个用户的盐 您需要先
  • 使用操作系统用户名/密码在 PHP 中进行身份验证?

    我想知道是否有一种方法可以使用 PHP 或者可能是其他一些 CGI 但最好是 PHP 来使用其操作系统 在本例中为 Linux Debian 5 用户名和密码来验证用户 可能的 难的 谢谢 一般来说 这种东西是特定于操作系统的 并与现有的身

随机推荐

  • BCC 发送 PHP mail() 到邮件列表的方式与 TO 不同吗?

    我正在改进 PHP 邮件列表代码 使用mail 在循环中迭代所有订阅者 该脚本用于显示 超出最大执行时间 30 秒 错误 我通过添加解决了该错误set time limit 0 现在没有错误 但发送 100 条消息花了大约七分钟 我有什么选
  • 如何了解System.Windows.Forms.dll中System.InvalidOperationException的详细信息?

    运行我的应用程序时 我在 Visual Studio 的 输出 面板中发现了下面的异常日志 System Windows Forms dll 中发生 System InvalidOperationException 类型的第一次机会异常 该
  • 动态像素化 html 图像元素

    我要在网页上拍摄图像 然后使用 javascript 或最适合的任何内容 对其进行动态 像素化 例如 变成 20px 的正方形 然后 当用户向下滚动页面时 我需要图像的分辨率逐渐增加 直到它不再像素化 我有什么想法可以去做这件事吗 我意识到
  • PayPal Express Checkout 集成响应

    我目前很难理解我的 PayPal EC 集成的响应 GetExpressCheckoutDetails 响应是 CHECKOUTSTATUS gt PaymentActionNotInitiated 但在 DoExpressCheckout
  • WPF设计问题(自定义控件或mvvm)

    这是场景 我有一个显示一些数据的视觉效果 The data to the visual can come in one of two ways 通过用户通过键盘或鼠标输入 通过一些后端源 Both these data inputs can
  • WooCommerce 上的购物车总重量和运输重新计算

    我正在尝试使用一个片段将我的自定义盒子重量添加到总订单重量中 目前工作正常 但是 不会根据重新计算的片段重量重新计算运输方式 有什么想法如何强制重新计算运费吗 add filter woocommerce cart contents wei
  • 完全删除 MySQL 5.7 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在尝试从 ubuntu 12 04 中完全卸载 mysql 但没能做到 我尝试了很多命令 但没有任何作用 任何人都可以帮忙吗 sudo apt g
  • 用于对基于时间的值进行排序的 Redis 数据结构设计

    我正在对数据流执行一些分析并将结果发布到 Redis 通道上 消费者订阅这些频道并获取实时数据源 所有历史数据分析结果都会丢失 现在我想添加在Redis中存储历史数据的能力 以便消费者可以查询这些历史数据 主要是按时间 由于分析结果按时间分
  • 如何在一项任务中执行多个 gulp 命令

    我很难理解如何在单个任务中处理多个 gulp 源 在这样的任务中 gulp task task1 function cb gulp src src js pipe gulp dest dist gulp src src css pipe g
  • 如何将 Linux shell 脚本编译为独立的可执行文件*二进制*(即不仅仅是 chmod 755)?

    我正在寻找一个免费的开源工具集 可以编译各种 经典 脚本语言 例如Korn Shell ksh csh bash 等作为可执行文件 如果脚本调用其他程序或可执行文件 则将它们包含在单个可执行文件中 Reasons 混淆交付给客户的代码 以免
  • 快速修复/n 错误:MsgSeqNum 太高

    我已经使用 QuickFIX n is v1 4 0 从此 创建了一个修复应用程序 http www quickfixn org download http www quickfixn org download 地点 当我执行应用程序时 我
  • 反序列化 xml,包括命名空间

    我正在尝试反序列化一些 XML 但无法获取名称空间 xsi type Model 上班 如果xsi type Model 被排除在 XML 之外 它可以工作 但它必须存在 如果我将命名空间保留在模型之外 则会收到错误 如果重命名它 则会得到
  • AngularJS 拦截并扩展控制器 $scope

    我在应用程序中定义了许多可重用的功能 每个控制器都与 scope 变量一起使用 有没有办法扩展 scope 变量 以便我可以在任何地方使用我的扩展代码 而不是每次都创建共享服务 就像是 I ve tested this out and it
  • 我希望我的 Android 应用程序仅在纵向模式下运行?

    我希望我的 Android 应用程序仅在纵向模式下运行 我怎样才能做到这一点 在清单中 为您的所有活动进行设置
  • PyDev 的导入错误

    我使用 PyDev Eclipse 已有几个月了 并且在导入时遇到了相同的错误 PyDev 在导入中用红色下划线并说Unresolved import xxx Found at yyy 当我点击yyyeclipse找到并打开该模块的执行 P
  • 安装了jSweet。怎么办?

    我有一个java项目 我想将其转换为Typescript 大约150个文件 As per http www jsweet org getting started http www jsweet org getting started 我查看
  • iPhone开发配置助手第3步公钥/私钥问题

    您好 我正在使用开发配置助手 在第 3 步 在 钥匙串访问 中验证您的私钥和公钥时 我在 钥匙串 gt 登录 中有 iPhone 开发人员 XXXXXXX 证书 但找不到任何密钥 如果我单击 类别 gt 键 我什么也看不到 我应该怎么做才能
  • Windows批处理脚本仅保留目录中的N个最新文件夹

    我有一个目录 我将 MySQL 数据库备份到具有当前日期的文件夹中 现在 30 或 60 天后 我喜欢只保留该备份目录中的 n 个最新文件夹 并删除其余文件夹 每个文件夹中都有 gzip 压缩的数据库 为了备份我使用的 MySQL 数据库a
  • QWebPage多次触发loadFinished()

    我正在使用 load 方法将内容加载到 QWebPage 中 但我的 loadStarted loadFinished 和 loadProgress 处理程序调用了多次 如何检测该页面已完全加载其所有内容 在以下位置发布了相关解决方案提案
  • 使用 $fetch 和 Pinia 的 Nuxt 3 JWT 身份验证

    我正在尝试对不同的 API 进行 JWT 身份验证 由于 nuxtjs auth next 似乎不是最新的 而且据我所知 可以在 Nuxt 3 中使用新的全局方法 fetch 而不是 nuxtjs axios 也不是最新的 我认为它自己编写