Remix Auth中destroySession返回[object Promise]无法清除会话问题
Remix会话销毁故障:destroySession返回[object Promise]无法清除会话
问题场景
在Remix应用中实现用户认证流程时,调用destroySession方法无法正常清除会话,反而返回[object Promise],导致登出功能失效。
相关代码
auth.server.js
import { hash, compare } from "bcryptjs"; import { prisma } from "./database.server"; import { createCookieSessionStorage, redirect } from "@remix-run/node"; export const sessionStorage = createCookieSessionStorage({ cookie: { secure: process.env.NODE_ENV === "production", path: "/", secrets: [process.env.SESSION_SECRET], sameSite: "lax", maxAge: 30 * 24 * 60 * 60, // 30 days httpOnly: true } }); async function createUserSession(userId, redirectPath) { const session = await sessionStorage.getSession(); session.set("userId", userId); return redirect(redirectPath, { headers: { "Set-Cookie": await sessionStorage.commitSession(session) } }); } export async function getUserFromSession(request) { const session = await sessionStorage.getSession( request.headers.get("Cookie") ); const userId = session.get("userId"); return userId ? userId : null; } export function destroyUserSession(request) { const session = sessionStorage.getSession(request.headers.get("Cookie")); return redirect("/", { headers: { "Set-Cookie": sessionStorage.destroySession(session) } }); } export async function login({ email, password }) { const existingUser = await prisma.user.findFirst({ where: { email } }); if (!existingUser) { return throwError( "Could not log you in, please check provided email.", 401 ); } const passwordCorrect = await compare(password, existingUser.password); if (!passwordCorrect) { return throwError( "Could not log you in, please check provided password.", 401 ); } return createUserSession(existingUser.id, "/"); } function throwError(text, code) { const error = new Error(text); error.status = code; // authentication error code throw error; // this triggers ErrorBoundary, as it's not an error response }
/routes/logout.js
import { json } from "@remix-run/node"; import { destroyUserSession } from "~/data/auth.server"; export function action({ request }) { if (request.method !== "POST") { throw json({ message: "Invalid request method" }, { status: 400 }); } return destroyUserSession(request); }
登出按钮组件
<Form method="post" action="/logout"> <button type="submit">Logout</button> </Form>
问题根源
destroyUserSession函数未使用await处理异步操作:
sessionStorage.getSession()是异步方法,返回Promise,直接赋值给session会得到Promise对象而非实际会话实例sessionStorage.destroySession()接收Promise作为参数时,同样返回Promise,导致Set-Cookie头被设置为[object Promise],无法正确清除会话
解决方法
将登出逻辑封装为异步函数并移入auth.server.js,同时确保所有异步操作都用await处理:
更新后的auth.server.js(新增logout函数)
在文件中添加以下异步函数:
export async function logout(request) { const session = await sessionStorage.getSession(request.headers.get("Cookie")); return redirect("/", { headers: { "Set-Cookie": await sessionStorage.destroySession(session) } }); }
更新后的/routes/logout.js
import { redirect } from "@remix-run/node"; import { logout } from "~/data/auth.server"; export const action = ({ request }) => logout(request); export const loader = () => redirect("/auth");
这样修改后,异步操作被正确等待,Set-Cookie头会被设置为会话销毁后的正确值,登出功能即可正常工作。
内容的提问来源于stack exchange,提问作者marwan37
相关产品推荐
相关产品推荐

