为你的 Nuxt 3 和 Vue 3 应用添加身份验证 (Logto)

发布: (2025年12月22日 GMT+8 19:45)
7 min read
原文: Dev.to

Source: Dev.to

(请提供需要翻译的正文内容,我才能为您完成简体中文翻译。)

开始之前:在控制台创建 Logto 应用

在 Logto 控制台中,创建一个与您的框架相匹配的应用:

框架Logto 应用类型
Nuxt 3Traditional Web
Vue 3Single Page Application (SPA)

您需要以下两个设置的值:

  • Endpoint – 您的租户 URL(例如 https://your-tenant.logto.app
  • App ID
  • App Secret仅适用于 Nuxt

第 1 部分 — Nuxt 3(SSR):使用 @logto/nuxt 添加认证

Nuxt 通常以 SSR(或混合渲染)方式部署。Logto 的 Nuxt SDK 为 SSR 设计,使用安全的 cookie + 服务器端处理来完成认证。

1️⃣ 安装 Nuxt SDK

npm i @logto/nuxt
# or
pnpm add @logto/nuxt
# or
yarn add @logto/nuxt

2️⃣ 添加环境变量

在项目根目录创建 .env 文件:

NUXT_LOGTO_ENDPOINT="https://your-tenant.logto.app"
NUXT_LOGTO_APP_ID="your-app-id"
NUXT_LOGTO_APP_SECRET="your-app-secret"
NUXT_LOGTO_COOKIE_ENCRYPTION_KEY="a-strong-random-string"

重要提示: NUXT_LOGTO_COOKIE_ENCRYPTION_KEY 必须是强随机字符串,因为它用于保护加密的认证 cookie。

3️⃣ 配置 nuxt.config.ts

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@logto/nuxt'],

  runtimeConfig: {
    logto: {
      endpoint: process.env.NUXT_LOGTO_ENDPOINT,
      appId: process.env.NUXT_LOGTO_APP_ID,
      appSecret: process.env.NUXT_LOGTO_APP_SECRET,
      cookieEncryptionKey: process.env.NUXT_LOGTO_COOKIE_ENCRYPTION_KEY,
    },
  },
})

4️⃣ 在 Logto 控制台配置重定向 URI

假设你的 Nuxt 应用运行在 http://localhost:3000

重定向类型URI
Redirect URI(登录回调)http://localhost:3000/callback
Post sign‑out redirect URI(登出后重定向)http://localhost:3000/

这些必须与 SDK 使用的回调和返回 URL 完全匹配。

5️⃣ 了解内置路由

Nuxt 模块会提供以下内置路由用于认证流程:

  • /sign-in
  • /sign-out
  • /callback

你可以自定义它们:

// nuxt.config.ts
export default defineNuxtConfig({
  logto: {
    pathnames: {
      signIn: '/login',
      signOut: '/logout',
      callback: '/auth/callback',
    },
  },
})

如果修改了回调路径,请相应地在 Logto 控制台更新重定向 URI。

6️⃣ 实现简易的登录 / 登出按钮

<script setup lang="ts">
const user = useLogtoUser()
</script>

<template>
  <button @click="user ? signOut() : signIn()">
    Sign {{ user ? 'out' : 'in' }}
  </button>

  <pre>{{ user }}</pre>
</template>

useLogtoUser() 是响应式的 — 会在会话变化时自动更新。

7️⃣ 请求额外的用户声明(Scopes)

默认情况下你只能获取基础 OIDC 声明。若想获取更多(例如 email、phone),需要添加 scopes:

// nuxt.config.ts
import { UserScope } from '@logto/nuxt'

export default defineNuxtConfig({
  logto: {
    scopes: [UserScope.Email, UserScope.Phone],
  },
})

8️⃣ 使用 Logto 客户端(仅服务器端)

useLogtoClient() 只能在服务器端使用;在客户端会返回 undefined。示例:在服务器端获取一次用户信息。

// composables/useServerUserInfo.ts
import { useLogtoClient, useState, callOnce } from '#imports'

export const useServerUserInfo = async () => {
  const client = useLogtoClient()
  const userInfo = useState('logto-user-info', () => null)

  await callOnce(async () => {
    if (!client) return
    if (!(await client.isAuthenticated())) return

    userInfo.value = await client.fetchUserInfo()
  })

  return userInfo
}

Source:

第 2 部分 — Vue 3(SPA):使用 Vue SDK 添加身份验证

Vue SPA 没有服务器运行时来安全地存储密钥,因此推荐的设置是使用 Logto Vue SDK 并在 Logto 控制台中配置 SPA 应用设置。

1️⃣ 安装 Vue SDK

npm i @logto/vue
# or
pnpm add @logto/vue
# or
yarn add @logto/vue

2️⃣ 在 Logto 控制台配置重定向 URI

假设你的 Vue 应用运行在 http://localhost:5173

重定向类型URI
Redirect URI(登录回调)http://localhost:5173/callback
Post sign‑out redirect URI(退出后重定向)http://localhost:5173/

(如果你的开发服务器地址不同,请使用实际的源地址。)

3️⃣ 在 main.ts 中初始化 Logto

// src/main.ts
import { createApp } from 'vue'
import { createLogto } from '@logto/vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(
  createLogto({
    endpoint: import.meta.env.VITE_LOGTO_ENDPOINT,
    appId: import.meta.env.VITE_LOGTO_APP_ID,
  })
)

app.use(router)
app.mount('#app')

4️⃣ 添加环境变量

创建一个 .env 文件(Vite 会公开以 VITE_ 为前缀的变量):

VITE_LOGTO_ENDPOINT="https://your-tenant.logto.app"
VITE_LOGTO_APP_ID="your-app-id"

添加回调路由

在单页面应用(SPA)中,您必须处理重定向回调路由。

使用 Vue Router 的示例

// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../pages/Home.vue'
import Callback from '../pages/Callback.vue'

export default createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/callback', component: Callback },
  ],
})

回调页面

<script setup lang="ts">
import { onMounted } from 'vue'
import { useLogto } from '@logto/vue'
import { useRouter } from 'vue-router'

const { handleSignInCallback } = useLogto()
const router = useRouter()

onMounted(async () => {
  await handleSignInCallback(window.location.href)
  router.replace('/')
})
</script>

<template>
  <p>Signing you in…</p>
</template>

登录 / 登出 按钮

<script setup lang="ts">
import { useLogto } from '@logto/vue'

const { isAuthenticated, signIn, signOut } = useLogto()

const handleSignIn = async () => {
  await signIn(import.meta.env.VITE_LOGTO_REDIRECT_URI)
}

const handleSignOut = async () => {
  await signOut(import.meta.env.VITE_LOGTO_POST_SIGN_OUT_REDIRECT_URI)
}
</script>

<template>
  <button @click="handleSignIn" v-if="!isAuthenticated">Sign in</button>
  <button @click="handleSignOut" v-else>Sign out</button>
</template>

添加重定向相关的环境变量

VITE_LOGTO_REDIRECT_URI="http://localhost:5173/callback"
VITE_LOGTO_POST_SIGN_OUT_REDIRECT_URI="http://localhost:5173/"

显示当前用户(可选)

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useLogto } from '@logto/vue'

const { isAuthenticated, getIdTokenClaims } = useLogto()
const claims = ref(null)

const loadClaims = async () => {
  claims.value = await getIdTokenClaims()
}
</script>

<template>
  <button @click="loadClaims" :disabled="!isAuthenticated">Load user claims</button>
  <pre v-if="claims">{{ claims }}</pre>
</template>

在 Nuxt 与 Vue 集成之间的选择

  • Nuxt(SSR 或混合渲染): 使用 @logto/nuxt。它专为服务器端流程和安全 Cookie 处理而构建。
  • Vue SPA(无服务器运行时): 使用 @logto/vue,并在 Logto 控制台中选择 SPA 应用类型。

快速检查

  • 点击 Sign in 应该将您重定向到 Logto 托管的登录界面。
  • 登录后,您应该进入回调路由并返回到应用。
  • 点击 Sign out 应该清除共享会话并重定向到登出后的 URL。

最终说明

本文故意保持示例简洁且面向生产。认证成功后,下一步通常是:

  • 保护路由(Nuxt 中间件 / Vue 路由守卫)
  • 使用访问令牌调用您的 API
  • 如果产品需要,添加组织/角色/权限
Back to Blog

相关文章

阅读更多 »

了解 JSON Web Token (JWT)

在创建 Web 应用程序的某个时刻,我们需要为系统开发一个认证解决方案。有多种策略可以实现,例如 aute...