You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:10:55