我有一个 NextJS 14 (Typescript) 应用程序并使用 Supabase 作为 Saas 后端。
我的 app/login/page.tsx 文件呈现以下组件:
'use client'
import { useFormState, useFormStatus } from 'react-dom';
import { signInUser } from '@/actions/auth'
const initialState = {
message: "",
}
function SubmitButton(){
const { pending } = useFormStatus()
return (
<button type="submit" aria-disabled={pending}>Bestätigen</button>
)
}
export default function SignInForm() {
const [state, sigInAction] = useFormState(signInUser, initialState)
return (
<div>
<h2>Register!</h2>
<form action={sigInAction}>
<div>
<label htmlFor="email">
Email
</label>
<input
type="email"
id="email"
name="email"
autoComplete="email"
required
/>
</div>
<div>
<label htmlFor="password">
Password
</label>
<input
id="password"
type="password"
name="password"
required
/>
</div>
<p aria-live="polite" role="status">
{state?.message}
</p>
<div>
<SubmitButton/>
</div>
</form>
</div>
);
}
actions/auth.ts 中的
signInUser
函数是:
"use server"
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { createServerClient, type CookieOptions } from '@supabase/ssr'
import { cookies } from 'next/headers'
import { redirect } from "next/navigation";
export async function signInUser(prevState: any, formData: FormData) {
console.log("Action")
const schema = z.object({
email: z.string().min(1),
password: z.string().min(1)
})
const signUpFormData = schema.parse({
email: formData.get("email"),
password: formData.get("password")
})
try {
const cookieStore = cookies()
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value
},
set(name: string, value: string, options: CookieOptions) {
cookieStore.set({ name, value, ...options })
},
remove(name: string, options: CookieOptions) {
cookieStore.set({ name, value: '', ...options })
},
},
}
)
const { data, error } = await supabase.auth.signInWithPassword({
email: signUpFormData.email,
password: signUpFormData.password,
})
if (error) {
console.log(error)
}
revalidatePath("/")
console.log("Should redirect now...")
redirect("/")
} catch (e){
return {message: "Error"}
}
}
这是我的中间件.ts:
import { createServerClient, type CookieOptions } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
console.log("Enter Middleware")
let response = NextResponse.next({
request: {
headers: request.headers,
},
})
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return request.cookies.get(name)?.value
},
set(name: string, value: string, options: CookieOptions) {
request.cookies.set({
name,
value,
...options,
})
response = NextResponse.next({
request: {
headers: request.headers,
},
})
response.cookies.set({
name,
value,
...options,
})
},
remove(name: string, options: CookieOptions) {
request.cookies.set({
name,
value: '',
...options,
})
response = NextResponse.next({
request: {
headers: request.headers,
},
})
response.cookies.set({
name,
value: '',
...options,
})
},
},
}
)
await supabase.auth.getSession();
const {
data: { user },
} = await supabase.auth.getUser()
// if user is not signed in and the current path is not /login redirect the user to /login
if (!user && !request.nextUrl.pathname.startsWith('/login')) {
console.log("redirect to /login")
return NextResponse.redirect(new URL('/login', request.url))
}
// if user is signed in and the current path is /login redirect the user to /
if (user && request.nextUrl.pathname === '/login') {
console.log("redirect to /")
return NextResponse.redirect(new URL('/', request.url))
}
return response
}
export const config = {
matcher: ['/', '/login'],
}
我正在使用以下依赖项:
我知道身份验证有效,但不幸的是重定向无效。重新加载页面时,我的中间件会自动重定向经过身份验证的用户。
有人可以帮助我为什么重定向不起作用吗?预先感谢。
我自己解决了。我不知道为什么,但是当我将
redirect("/")
放在我的 try
-catch
块之外时,它可以正常工作。