You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt 3 结合 Laravel 9 与 Sanctum 认证方案实现咨询

Nuxt3 + Laravel Sanctum 身份认证实现方案

一、基础环境配置

Laravel Sanctum 端配置

  1. 在 .env 中设置允许的前端域名:
    SANCTUM_STATEFUL_DOMAINS=your-nuxt-app-domain.test
    SESSION_DOMAIN=.your-root-domain.test # 跨域场景下设置根域名
    
  2. 配置 config/cors.php,允许前端域名的请求:
    'allowed_origins' => [env('FRONTEND_URL', 'http://your-nuxt-app-domain.test')],
    'allowed_methods' => ['*'],
    'allowed_headers' => ['*'],
    'supports_credentials' => true,
    

Nuxt3 端配置

在 nuxt.config.ts 中配置 API 地址与 cookie 规则:

export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiBase: process.env.NUXT_PUBLIC_API_BASE_URL || 'http://your-laravel-api.test'
    }
  },
  modules: ['@pinia/nuxt'], // 后续用Pinia管理认证状态
  cookies: {
    defaults: {
      path: '/',
      sameSite: 'lax'
    }
  }
})

封装带 Sanctum 要求的请求工具:

// composables/useApi.ts
export const useApi = () => {
  const config = useRuntimeConfig()
  return $fetch.create({
    baseURL: config.public.apiBase,
    credentials: 'include', // 强制携带cookie,Sanctum依赖此维持会话
    headers: {
      'Accept': 'application/json',
      'X-Requested-With': 'XMLHttpRequest' // Sanctum要求的标识头
    }
  })
}

二、登录功能实现

1. 安装并配置 Pinia

执行安装命令:

npm install @pinia/nuxt

创建认证状态管理 store:

// stores/auth.ts
import { defineStore } from 'pinia'

export const useAuthStore = defineStore('auth', () => {
  const user = useState('auth_user', () => null)
  const isAuthenticated = computed(() => !!user.value)

  // 登录方法
  const login = async (credentials: { email: string, password: string }) => {
    const api = useApi()
    try {
      await api('/sanctum/csrf-cookie') // 跨域场景下必须先获取CSRF令牌
      const res = await api('/api/login', {
        method: 'POST',
        body: credentials
      })
      user.value = res.user
      return true
    } catch (err) {
      console.error('登录失败', err)
      return false
    }
  }

  // 登出方法
  const logout = async () => {
    const api = useApi()
    try {
      await api('/api/logout', { method: 'POST' })
      user.value = null
    } catch (err) {
      console.error('登出失败', err)
    }
  }

  // 刷新页面后验证登录状态
  const fetchUser = async () => {
    const api = useApi()
    try {
      const res = await api('/api/user')
      user.value = res
    } catch (err) {
      user.value = null
    }
  }

  return { user, isAuthenticated, login, logout, fetchUser }
})

2. 登录页面实现

<!-- pages/login.vue -->
<template>
  <form @submit.prevent="handleLogin">
    <input v-model="form.email" type="email" placeholder="邮箱" required />
    <input v-model="form.password" type="password" placeholder="密码" required />
    <button type="submit">登录</button>
    <p v-if="loginError" class="text-red-500">登录失败,请检查账号密码</p>
  </form>
</template>

<script setup>
const authStore = useAuthStore()
const form = reactive({ email: '', password: '' })
const loginError = ref(false)

const handleLogin = async () => {
  loginError.value = false
  const success = await authStore.login(form)
  if (success) {
    navigateTo('/') // 登录成功跳转首页
  } else {
    loginError.value = true
  }
}
</script>

三、路由保护:Auth 中间件

全局中间件(拦截所有路由)

创建 middleware/auth.global.ts:

export default defineNuxtRouteMiddleware(async (to) => {
  const authStore = useAuthStore()
  await authStore.fetchUser() // 每次路由跳转验证登录状态

  // 定义无需认证的路由列表
  const publicRoutes = ['/login', '/', '/about']
  const isPublicRoute = publicRoutes.includes(to.path)

  if (!authStore.isAuthenticated && !isPublicRoute) {
    return navigateTo('/login') // 未登录访问私有路由,跳转登录页
  }
  if (authStore.isAuthenticated && to.path === '/login') {
    return navigateTo('/') // 已登录访问登录页,跳转首页
  }
})

局部中间件(仅拦截指定路由)

创建 middleware/auth.ts:

export default defineNuxtRouteMiddleware(async () => {
  const authStore = useAuthStore()
  await authStore.fetchUser()

  if (!authStore.isAuthenticated) {
    return navigateTo('/login')
  }
})

在需要保护的页面中启用:

<!-- pages/dashboard.vue -->
<script setup>
definePageMeta({
  middleware: 'auth'
})
</script>

四、@nuxtjs-alt/auth 包 $auth undefined 问题修复

如果坚持使用该包,需注意以下几点:

  1. 确保模块正确注册:
    // nuxt.config.ts
    modules: ['@nuxtjs-alt/auth', '@nuxtjs-alt/axios']
    
  2. 配置 Sanctum 策略:
    auth: {
      strategies: {
        sanctum: {
          provider: 'laravel/sanctum',
          url: process.env.NUXT_PUBLIC_API_BASE_URL,
          endpoints: {
            login: { url: '/api/login', method: 'post' },
            logout: { url: '/api/logout', method: 'post' },
            user: { url: '/api/user', method: 'get' }
          }
        }
      },
      globalMiddleware: true
    }
    
  3. 在组件中使用 useAuth() 替代 nuxtApp().$auth:
    const { login, user, loggedIn } = useAuth()
    

内容的提问来源于stack exchange,提问作者Giampy71

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 19:51:02