我正在使用 Next.js 14 和 TypeScript 开发一个项目,其中我有两个角色:买家和卖家。在注册过程中,用户需要选择自己的角色,并根据此选择将他们重定向到适当的仪表板(买方或卖方的仪表板)。然而,我在实现处理这种基于角色的逻辑的注册 API 时遇到了麻烦。
以下是设置概述:
注册流程:
用户填写注册表单,包括电子邮件地址、全名和密码。
提交表格后,用户选择自己是买家还是卖家。
根据角色,用户将被重定向到相应的仪表板(/dashboard/buyer 或 /dashboard/seller)。
遇到的问题:
用户提交表单后,API 无法正确处理基于角色的重定向。
有时用户的角色未正确保存,或者重定向未按预期发生。
我在 Next.js 中使用服务器操作进行表单提交和身份验证,避免使用 API 路由。
这是我正在使用的代码的简化版本:
async function handleSignUp(data: FormData) {
"use server";
const role = data.get('role'); // buyer or seller
const email = data.get('email');
const password = data.get('password');
try {
// sign-up logic here
if (role === 'buyer') {
return { redirect: '/dashboard/buyer' };
} else if (role === 'seller') {
return { redirect: '/dashboard/seller' };
}
} catch (error) {
console.error('Sign-up error:', error);
}
}
我尝试过的:
调试表单数据,确保角色传递正确。
检查表单提交后的重定向逻辑。
使用服务器操作替代 API 路由。
问题:
如何在 Next.js 13 中正确实现注册 API 来处理基于角色的重定向?
是否有通过服务器操作在 Next.js 中管理基于角色的身份验证和重定向的最佳实践?
任何建议或例子将不胜感激!
假设您在用户注册时将用户详细信息(包括角色)保存在表中,并且使用
next-auth
进行身份验证,则可以在注册成功后立即触发 next-auth
登录功能。以下是带有 CredentialsProvider
的示例。
提供的中间件示例还将处理授权逻辑。根据您的要求定制
从服务器端或中间件处理基于角色的身份验证总是更好。
//下一个身份验证route.ts文件CredentialsProvider
CredentialsProvider({
//@ts-expect-error
async authorize(credentials, _req) {
//@ts-expect-error
const user: User = await getUser(credentials.email) // write your function to get user details including password, role from db;
// do user not exist check and other checks here
// validate password
const isValid = await verifyPassword(
//@ts-expect-error
credentials.password,
user.password
);
if (!isValid) {
throw Error("Wrong Password");
}
//here instead of image, I am returning user role
return {
image: user.role,
email: user.email,
name: user.name,
};
},
}),
// middleware.tsx(在项目根目录下创建此文件)
import { NextFetchEvent, NextRequest, NextResponse } from "next/server";
import { getToken } from "next-auth/jwt";
import { withAuth } from "next-auth/middleware";
export default async function middleware(
req: NextRequest,
event: NextFetchEvent
) {
const PUBLIC_FILE = /\.(.*)$/;
const pathname = req.nextUrl.pathname;
const token = await getToken({ req });
const isAuthenticated = !!token;
// token will have 3 keys: name, picture ("image" which we set on CredentialsProvider),email
if(isAuthenticated && pathname=="/dashboard"){
if(token.picture=="buyer"){
return NextResponse.redirect(new URL("/dashboard/buyer", req.url));
}else if(token.picture=="seller"){
return NextResponse.redirect(new URL("/dashboard/seller", req.url));
}
}
// Allow users to access URLs on following conditions, edit as per the requirement
if (
pathname.startsWith("/_next") ||
pathname. Includes("/api") ||
pathname. Includes("/signup")
PUBLIC_FILE.test(pathname) ||
isAuthenticated
) {
return NextResponse.next();
}
// apart from above conditions if user is not authenticated, it will redirect to /login route
const authMiddleware = withAuth({
pages: {
signIn: "/login",
},
});
// @ts-expect-error
return authMiddleware(req, event);
}
//登录功能
import { signIn } from "next-auth/react";
//after successful signup
const result = await signIn("credentials", {
redirect: false,
email: "email",
password:"password",
});
setLoading(false);
if (result && !result. Error) {
//success scenario, this is just a dummy route, middleware will redirect this as per the role
router.replace("/dashboard");
} else if (result?.error) {
//failed scenario
}