I使用next.js 15。如下所示,我将服务器操作“ Onlogin”传递给了称为“登录名”的客户端组件。当用户单击表单中的登录按钮时,该操作是调用的。在服务器操作中,我实例化了一个身份验证程序类,该类负责将提供的凭据发送到服务器,并使用cookie()。设置(“ ...”)保存接收到的访问令牌并返回身份验证状态。如果身份验证成功,客户端组件将将用户发送到下一页。在我的理解中,我遵循有关在服务器操作中操纵cookie的文档。但是,我遇到了“只能在服务器操作或路由处理程序中修改cookie”。我想念什么?是因为我将身份验证流委托给身份验证类别类别吗?与示例相比,这是我看到的唯一区别。奇怪的是,这种确切的实现以前起作用并停止工作,而我却没有意识到我所做的任何更改。
export async function LoginPage() {
async function onLogin(state: LoginFormState, formData: FormData): Promise<LoginFormState> {
"use server";
const username = formData.get("username")?.toString();
const password = formData.get("password")?.toString();
const authenticator = new Authenticator()
return authenticator.authenticate(username, password)
};
return (
<LoginForm formAction={ onLogin }/>
);
}
在这里客户组件
'use client';
export function LoginForm({ formAction }: Props) {
const [isRejected, setIsRejected] = useState(false);
const [state, action] = useActionState<LoginFormState, FormData>(formAction, {});
const router = useRouter()
useEffect(() => {
if (state.errorState?.unauthorized) {
setIsRejected(true)
}
if (state.successState) router.push('/clients')
}, [state]);
return (
<div className="flex h-screen">
<div className="secondary-color-background m-auto p-8 sm:rounded-md flex flex-col justify-center items-center">
<form action={action} className="">
<label className="block mb-6">
<span className="h2 white-color">Username</span>
<input name="username" type="text" className={`${state.errorState?.username ? "border-orange" : ""} w-full border-2 rounded p-2 focus:outline-none focus:bg-white focus:border-primary `}
placeholder="type here"/>
</label>
<label className="block mb-6">
<span className="h2 white-color">Password</span>
<input name="password" type="password" className={`${state.errorState?.password ? "border-orange" : ""} w-full border-2 rounded p-2 focus:outline-none focus:bg-white focus:border-primary `}
placeholder="type here" />
</label>
<div className="flex flow-root w-full content-start items-end">
<ShakeButton text="Inloggen" isShaking= { isRejected } onStop= { () => setIsRejected(false) }/>
<Link className="body2 text-primary ml-4" href={"/komt nog"}>
Ik ben mijn wachtwoord vergeten
</Link>
</div>
</form>
</div>
</div>
);
}
因子:cookies必须在服务器操作中设置 next.js需要cookie()。设置(...)在服务器操作的执行范围内运行。如果在Authenticator中进行处理,则Next.js不会将其识别为有效的修改。 有可能的解决方案1:
移动cookie()。设置(...)到服务器操作 像这样更新Onlogin:
export async function LoginPage() {
async function onLogin(state: LoginFormState, formData: FormData): Promise<LoginFormState> {
"use server";
const username = formData.get("username")?.toString();
const password = formData.get("password")?.toString();
const authenticator = new Authenticator();
const result = await authenticator.authenticate(username, password);
if (result.success && result.token) {
import("next/headers").then(({ cookies }) => {
cookies().set("access_token", result.token, { httpOnly: true, secure: true });
});
}
return result;
};
return <LoginForm formAction={onLogin} />;
}
authenticator仅返回令牌而不是修改cookie。
Import(“ Next/headers”)确保正确访问Cookie()。 // actions/auth.ts
"use server";
import { cookies } from "next/headers";
import { Authenticator } from "@/lib/authenticator";
export async function onLogin(state: LoginFormState, formData: FormData): Promise<LoginFormState> {
const username = formData.get("username")?.toString();
const password = formData.get("password")?.toString();
const authenticator = new Authenticator();
const result = await authenticator.authenticate(username, password);
if (result.success && result.token) {
cookies().set("access_token", result.token, { httpOnly: true, secure: true });
}
return result;
}
export function LoginPage() {
return <LoginForm formAction={onLogin} />;
}