英文:
Composable for checking Laravel Sanctum's CSRF token in Nuxt 3
问题
I'm working on a Nuxt 3 app with Laravel 9 as API with Sanctum and Fortify.
I wrote a composable to check the response to the Laravel Sanctum's CSRF token HTTP route '(/sanctum/csrf-cookie)' and I'm trying to check if it's working by logging via 'console.log()' the composable's state, but it always shows an empty Proxy received as error.
Please help, what am I doing wrong?
Here is what I've done so far:
The composable: 'auth.ts' :
export function useCsrfToken() {
const baseURL = useRuntimeConfig().public.LARAVEL_BASE_URL
const options = {
baseURL,
credentials: 'include',
headers: {
Accept: 'application/json',
} as HeadersInit,
method: 'GET',
}
const state = ref({
status: '',
error: {},
})
async function getCsrfToken() {
state.value.error = {}
state.value.status = '';
await $fetch('/sanctum/csrf-cookie', options)
.then(() => (state.value.status = 'ok'))
.catch((error) => {
console.log('error from useCsrfToken', error)
state.value.error = { error }
})
}
getCsrfToken()
return { state }
}
The login Nuxt page, where I'm using the above composable :
<script setup>
definePageMeta({
layout: false,
})
const submit = () => {
form.processing = true
const { state } = useCsrfToken()
console.log('error from login', state.value.error)
}
const form = reactive({
email: '',
password: '',
remember: false,
processing: false,
errors: {},
})
</script>
<template>
<div>
<!-- <TheTwoFactorChallenge v-if="verification" @2fapassed="submit" /> -->
<NuxtLayout name="auth">
<template #title>
<p class="card-header-title">Inicie Sesión</p>
</template>
<form novalidate @submit.prevent="submit">
<div class="field">
<label class="label" for="email">Usuario</label>
<div class="control has-icons-left has-icons-right">
<AppInput
type="email"
id="email"
v-model="form.email"
:error="form.errors?.email"
autocomplete="email"
required
/>
<AppIconLeft icon="fa-solid fa-envelope" />
<AppIconError v-if="form.errors?.email" class="is-right" />
</div>
<AppHelpError :errors="form.errors?.email" />
</div>
<div class="field">
<label class="label" for="password">Contraseña</label>
<div class="control has-icons-left has-icons-right">
<AppInput
type="password"
id="password"
v-model="form.password"
:error="form.errors?.password"
autocomplete="new-password"
required
/>
<AppIconLeft icon="fa-solid fa-lock" />
<AppIconError v-if="form.errors?.password" class="is-right" />
</div>
<AppHelpError :errors="form.errors?.password" />
</div>
<div class="field">
<div class="control">
<AppSwitch
id="remember"
v-model:checked="form.remember"
class="is-small is-link"
/>
<label for="remember">Recuérda me</label>
</div>
</div>
<div class="is-flex is-justify-content-flex-end mb-4">
<NuxtLink to="#">¿Olvidó su contraseña?</NuxtLink>
</div>
<div class="field">
<div class="control">
<AppButton
class="is-link is-fullwidth"
type="submit"
:is-loading="form.processing"
>Entrar</AppButton>
</div>
</div>
</form>
</NuxtLayout>
</div>
</template>
And here are the outputs:
英文:
I'm working on a Nuxt 3 app with Laravel 9 as API with Sanctum and Fortify.
I wrote a composable to check the response to the Laravel Sanctum's CSRF token HTTP route ('/sanctum/csrf-cookie')
and I'm trying to check if it's working by logging via console.log()
the composable's state, but it always shows an empty Proxy received as error.
Please help, what am I doing wrong?
Here is what I've done so far:
The composable: auth.ts
:
export function useCsrfToken() {
const baseURL = useRuntimeConfig().public.LARAVEL_BASE_URL
const options = {
baseURL,
credentials: 'include',
headers: {
Accept: 'application/json',
} as HeadersInit,
method: 'GET',
}
const state = ref({
status: '',
error: {},
})
async function getCsrfToken() {
state.value.error = {}
state.value.status = ''
await $fetch('/sanctum/csrf-cookie', options)
.then(() => (state.value.status = 'ok'))
.catch((error) => {
console.log('error from useCsrfToken', error)
state.value.error = { error }
})
}
getCsrfToken()
return { state }
}
The login Nuxt page, where I'm using the above composable :
<script setup>
definePageMeta({
layout: false,
})
const submit = () => {
form.processing = true
const { state } = useCsrfToken()
console.log('error from login', state.value.error)
// console.log('status from login', status)
}
const form = reactive({
email: '',
password: '',
remember: false,
processing: false,
errors: {},
})
</script>
<template>
<div>
<!-- <TheTwoFactorChallenge v-if="verification" @2fapassed="submit" /> -->
<NuxtLayout name="auth">
<template #title>
<p class="card-header-title">Inicie Sesión</p>
</template>
<form novalidate @submit.prevent="submit">
<div class="field">
<label class="label" for="email">Usuario</label>
<div class="control has-icons-left has-icons-right">
<AppInput
type="email"
id="email"
v-model="form.email"
:error="form.errors?.email"
autocomplete="email"
required
/>
<AppIconLeft icon="fa-solid fa-envelope" />
<AppIconError v-if="form.errors?.email" class="is-right" />
</div>
<AppHelpError :errors="form.errors?.email" />
</div>
<div class="field">
<label class="label" for="password">Contraseña</label>
<div class="control has-icons-left has-icons-right">
<AppInput
type="password"
id="password"
v-model="form.password"
:error="form.errors?.password"
autocomplete="new-password"
required
/>
<AppIconLeft icon="fa-solid fa-lock" />
<AppIconError v-if="form.errors?.password" class="is-right" />
</div>
<AppHelpError :errors="form.errors?.password" />
</div>
<div class="field">
<div class="control">
<AppSwitch
id="remember"
v-model:checked="form.remember"
class="is-small is-link"
/>
<label for="remember">Recuérdame</label>
</div>
</div>
<div class="is-flex is-justify-content-flex-end mb-4">
<NuxtLink to="#" class="has-text-link">
¿Olvidó su contraseña?
</NuxtLink>
</div>
<div class="field">
<div class="control">
<AppButton
class="is-link is-fullwidth"
type="submit"
:is-loading="form.processing"
>Entrar</AppButton
>
</div>
</div>
</form>
</NuxtLayout>
</div>
</template>
答案1
得分: 1
自Nuxt3提供了一个Server函数,可以用作API,因此很容易与Laravel混淆。
你可能需要添加一个proxy_pass
(如果你使用Nginx)来区分Nuxt和Laravel的请求,以便在Nuxt和Laravel之间共享相同的来源(以避免在Same-Origin-Policy上浪费时间)。
例如:
http://example.com/ // -> nuxt
http://example.com/api/ // -> laravel
(由于你说你在使用Docker,我将假设你正在使用laravel sail)
- 首先,为您的站点添加一个域名(例如
http://example.test
),而不是http://localhost
。 - 自定义
/sanctum/csrf-cookie
路由为/api/sanctum/csrf-cookie
(您可以在这里看到如何更改laravel sanctum csrf cookie路由) - 在Nginx配置中为
http://example.test/api/*
添加一个proxy_pass
:
location ~* ^/(api|broadcasting|storage)/ {
proxy_pass http://localhost:8080; // 您的laravel运行的地方
}
但是,在我的观点中,SSR Nuxt应该被视为一个客户端,与Android应用程序或iOS应用程序一样,因为前端和后端与以前将前端代码和后端代码放在同一个项目中相比是完全不同的项目。
因此,你可以像对待Android应用一样对待web,而不是启用CRSF保护。
这是一个Nuxt3 + Laravel的完整示例,使用了Laravel Sanctum并且具有授权功能。 👉 Laravel + SSR Nuxt3 with authorizations
英文:
Since Nuxt3 provides a Server function which could use as an API, it could be easily confused with Laravel.
You may need to add a proxy_pass
(if you use Nginx) to distinguish between Nuxt and Laravel requests in order to share the same origin between Nuxt and Laravel (to avoid wasting a second on Same-Origin-Policy )
For example:
http://example.com/ // -> nuxt
http://example.com/api/ // -> laravel
(Since you said you are using Docker, I'm going to assume you're using laravel sail)
- First, add a domain (for example
http://example.test
) for your site instead ofhttp://localhost
. - Custom the
/sanctum/csrf-cookie
route to/api/sanctum/csrf-cookie
(here you can see how to change laravel sanctum csrf cookie route) - Add a
proxy_pass
forhttp://example.test/api/*
in Nginx configs:
location ~* ^/(api|broadcasting|storage)/ {
proxy_pass http://localhost:8080; // where your laravel running
}
But, in my view, the SSR Nuxt should be considered as a client just equal to an Android app or IOS app, because the frontend and the backend are entire two different projects compared with the previous time when putting your frontend code and backend code in the same project.
So, you may auth the web just like auth the Android app, instead of booting the CRSF protection.
And here is a full example of Nuxt3 + Laravel, which is using Laravel Sanctum and also SSR with authorizations. 👉 Laravel + SSR Nuxt3 with authorizations
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论