透過 100 多個訣竅學習 Nuxt!

會話和身份驗證

身份驗證是 Web 應用程式中非常常見的需求。此食譜將向您展示如何在 Nuxt 應用程式中實作基本的使用者註冊和身份驗證。

簡介

在此食譜中,我們將使用 Nuxt Auth Utils 在全端 Nuxt 應用程式中設定身份驗證,它提供了用於管理客戶端和伺服器端會話資料的便捷工具。

此模組使用安全且密封的 Cookie 來儲存會話資料,因此您無需設定資料庫來儲存會話資料。

安裝 nuxt-auth-utils

使用 nuxi CLI 安裝 nuxt-auth-utils 模組。

終端機
npx nuxi@latest module add auth-utils
此命令將安裝 nuxt-auth-utils 作為依賴項,並將其推送到 nuxt.config.tsmodules 區段中

由於 nuxt-auth-utils 使用密封的 Cookie 來儲存會話資料,因此會話 Cookie 會使用來自 NUXT_SESSION_PASSWORD 環境變數的密鑰進行加密。

如果未設定,此環境變數將在開發模式下執行時自動新增至您的 .env
.env
NUXT_SESSION_PASSWORD=a-random-password-with-at-least-32-characters
您需要在部署之前將此環境變數新增至您的生產環境。

登入 API 路由

對於此食譜,我們將建立一個簡單的 API 路由,以根據靜態資料登入使用者。

讓我們建立一個 /api/login API 路由,該路由將接受 POST 請求,並在請求主體中包含電子郵件和密碼。

server/api/login.post.ts
import { z } from 'zod'

const bodySchema = z.object({
  email: z.string().email(),
  password: z.string().min(8)
})

export default defineEventHandler(async (event) => {
  const { email, password } = await readValidatedBody(event, bodySchema.parse)

  if (email === 'admin@admin.com' && password === 'iamtheadmin') {
    // set the user session in the cookie
    // this server util is auto-imported by the auth-utils module
    await setUserSession(event, {
      user: {
        name: 'John Doe'
      }
    })
    return {}
  }
  throw createError({
    statusCode: 401,
    message: 'Bad credentials'
  })
})
請確保在您的專案中安裝 zod 依賴項 (npm i zod)。
閱讀更多有關 nuxt-auth-utils 公開的 setUserSession 伺服器協助程式的資訊。

登入頁面

此模組公開一個 Vue 可組合項,以了解使用者是否已在我們的應用程式中通過身份驗證

<script setup>
const { loggedIn, session, user, clear, fetch } = useUserSession()
</script>

讓我們建立一個登入頁面,其中包含一個表單,用於將登入資料提交到我們的 /api/login 路由。

pages/login.vue
<script setup lang="ts">
const { loggedIn, user, fetch: refreshSession } = useUserSession()
const credentials = reactive({
  email: '',
  password: '',
})
async function login() {
  $fetch('/api/login', {
    method: 'POST',
    body: credentials
  })
  .then(async () => {
    // Refresh the session on client-side and redirect to the home page
    await refreshSession()
    await navigateTo('/')
  })
  .catch(() => alert('Bad credentials'))
}
</script>

<template>
  <form @submit.prevent="login">
    <input v-model="credentials.email" type="email" placeholder="Email" />
    <input v-model="credentials.password" type="password" placeholder="Password" />
    <button type="submit">Login</button>
  </form>
</template>

保護 API 路由

保護伺服器路由是確保您的資料安全的關鍵。客戶端中介軟體對使用者很有幫助,但如果沒有伺服器端保護,您的資料仍然可以被存取。保護任何包含敏感資料的路由至關重要,如果使用者未登入,我們應在這些路由上傳回 401 錯誤。

auth-utils 模組提供了 requireUserSession 實用程式函式,以協助確保使用者已登入並具有有效的會話。

讓我們建立一個只有通過身份驗證的使用者才能存取的 /api/user/stats 路由範例。

server/api/user/stats.get.ts
export default defineEventHandler(async (event) => {
  // make sure the user is logged in
  // This will throw a 401 error if the request doesn't come from a valid user session
  const { user } = await requireUserSession(event)

  // TODO: Fetch some stats based on the user

  return {}
});

保護應用程式路由

我們的資料在伺服器端路由到位後是安全的,但在不做任何其他事情的情況下,未經身份驗證的使用者在嘗試存取 /users 頁面時可能會收到一些奇怪的資料。我們應該建立一個 客戶端中介軟體,以保護客戶端的路由並將使用者重新導向到登入頁面。

nuxt-auth-utils 提供了一個方便的 useUserSession 可組合項,我們將使用它來檢查使用者是否已登入,如果未登入,則將他們重新導向。

我們將在 /middleware 目錄中建立中介軟體。與伺服器端不同,客戶端中介軟體不會自動套用至所有端點,我們需要指定要套用它的位置。

middleware/authenticated.ts
export default defineNuxtRouteMiddleware(() => {
  const { loggedIn } = useUserSession()

  // redirect the user to the login screen if they're not authenticated
  if (!loggedIn.value) {
    return navigateTo('/login')
  }
})

首頁

現在我們有了應用程式中介軟體來保護我們的路由,我們可以在顯示我們通過身份驗證的使用者資訊的首頁上使用它。如果使用者未通過身份驗證,他們將被重新導向到登入頁面。

我們將使用 definePageMeta 將中介軟體套用至我們要保護的路由。

pages/index.vue
<script setup lang="ts">
definePageMeta({
  middleware: ['authenticated'],
})
  
const { user, clear: clearSession } = useUserSession()

async function logout() {
  await clearSession()
  await navigateTo('/login')
}
</script>

<template>
  <div>
    <h1>Welcome {{ user.name }}</h1>
    <button @click="logout">Logout</button>
  </div>
</template>

我們還新增了一個登出按鈕,以清除會話並將使用者重新導向到登入頁面。

結論

我們已成功在 Nuxt 應用程式中設定了非常基本的使用者身份驗證和會話管理。我們還保護了伺服器端和客戶端上的敏感路由,以確保只有通過身份驗證的使用者才能存取它們。

接下來,您可以

查看開源的 atidone 儲存庫,其中包含一個使用 OAuth 身份驗證、資料庫和 CRUD 操作的 Nuxt 應用程式完整範例。