在next.js13中在浏览器中设置cookie后无法检索cookie

问题描述 投票:0回答:1

在 Next.js v13 中,我尝试使用身份验证,并且想将 JWT 令牌存储在 cookie 中,我能够存储它,但无法检索它,我尝试使用多个库(例如: cookie、js-cookie、cookies-next)甚至尝试使用“next/headers”中的 cookie,但仍然无法在服务器组件和客户端组件中检索它。

“应用程序/api/auth/loginUser/route.js”

import User from "@/app/_models/User";
import connectDB from "@/app/lib/connectdb";
import { AES, enc } from "crypto-js";
import { NextResponse } from "next/server";
import { sign } from "jsonwebtoken";
import { serialize } from "cookie";

const MAX_AGE = 60 * 60 * 24 * 2;

export async function POST(request) {
    try {
        connectDB();

        const { email, password } = await request.json();
        const user = await User.findOne({ email: email });

        if (!user)
            return new NextResponse(
                JSON.stringify({
                    success: false,
                    message: "Invalid credentials",
                })
            );

        const dycPassword = AES.decrypt(
            user.password,
            process.env.CRYPT_SECRET_KEY
        ).toString(enc.Utf8);

        if (dycPassword !== password) {
            return new NextResponse(
                JSON.stringify({
                    success: false,
                    message: "Invalid credentials",
                })
            );
        }

        const token = sign(user.toObject(), process.env.JWT_SECRET_KEY, {
            expiresIn: "2d",
        });

        const setCookie = serialize("userToken", token, {
            httpOnly: true,
            secure: process.env.NODE_ENV === "production",
            sameSite: "strict",
            maxAge: MAX_AGE,
            path: "/",
            httpOnly: false,
        });

        return new NextResponse(
            JSON.stringify({
                success: true,
                message: "Welcome!!!",
            }),
            { status: 200, headers: { "Set-Cookie": setCookie } }
        );
    } catch (error) {
        return new NextResponse(
            JSON.stringify({ success: false, message: error.message }),
            { status: 500 }
        );
    }
}

“应用程序/api/auth/me/route.js”

import { cookies } from "next/headers";
import { NextResponse } from "next/server";

export async function POST(req) {
    try {
        const cookieStore = cookies();
        const token = cookieStore.get("userToken");

        console.log(cookieStore.getAll(), token);

        return new NextResponse(
            JSON.stringify({ success: true, token: token }, { status: 200 })
        );
    } catch (error) {
        return new NextResponse(
            JSON.stringify({ success: false, message: error.message }),
            { status: 500 }
        );
    }
}

“应用程序/page.jsx”

import React from "react";
import { cookies } from "next/headers";

export const dynamic = "force-static";

export default async function Page() {
    const token = cookies().get("userToken");
    const data = await fetch("http://localhost:3000/api/auth/me", {
        method: "POST",
    }).then((data) => data.json());

    console.log(data);

    return (
        <div>
            <ul>{token}</ul>
        </div>
    );
}

上面的代码可以存储cookie,但无法检索它。我从 console.logs 得到的都是空对象、数组或未定义

依赖列表:

"dependencies": {
    "@headlessui/react": "^1.7.17",
    "@heroicons/react": "^2.0.18",
    "cookie": "^0.5.0",
    "crypto-js": "^4.1.1",
    "jsonwebtoken": "^9.0.2",
    "mongoose": "^7.5.3",
    "next": "latest",
    "next-themes": "^0.2.1",
    "react": "latest",
    "react-dom": "latest",
    "react-switch": "^7.0.0",
    "react-toastify": "^9.1.3",
    "sass": "^1.68.0"
},
"devDependencies": {
    "autoprefixer": "latest",
    "eslint": "latest",
    "eslint-config-next": "latest",
    "postcss": "latest",
    "tailwindcss": "latest"
}

更新:
所以我正在尝试标头,结果标头没有发送到我需要 cookie 的页面,当我使用 ThunderClient (VS 代码扩展)发出请求时,我能够获取我设置的 cookie ThunderClient 但在像 chrome 和 Edge 这样的浏览器中,标头只是空的,它们没有 cookie 或任何东西,所以要检查我是否创建了一个中间件和 console.log 标头,所以在中间件中所有的东西都存在,但是,它们没有被发送到我需要它们的服务器组件(“app/page.js”)。

中间件.js

import { NextResponse } from "next/server";

// This function can be marked `async` if using `await` inside
export async function middleware(request) {
    console.log(request.headers.get("cookie"));
    return NextResponse.next({
        request: {
            headers: new Headers(request.headers),
        },
    });
}

// See "Matching Paths" below to learn more
export const config = {
    matcher: "/",
};

我在“app/page.js”中获得的标题:

HeadersList {
  cookies: null,
  [Symbol(headers map)]: Map(0) {},
  [Symbol(headers map sorted)]: null
}

我在“app/api/auth/me/route.js”中获得的标头:

HeadersList {
  cookies: null,
  [Symbol(headers map)]: Map(10) {
    'accept' => { name: 'accept', value: '*/*' },
    'accept-encoding' => { name: 'accept-encoding', value: 'gzip, deflate' },
    'accept-language' => { name: 'accept-language', value: '*' },
    'cache-control' => { name: 'cache-control', value: 'no-cache' },
    'connection' => { name: 'connection', value: 'keep-alive' },
    'content-length' => { name: 'content-length', value: '0' },
    'host' => { name: 'host', value: 'localhost:3000' },
    'pragma' => { name: 'pragma', value: 'no-cache' },
    'sec-fetch-mode' => { name: 'sec-fetch-mode', value: 'cors' },
    'user-agent' => { name: 'user-agent', value: 'undici' }
  },
  [Symbol(headers map sorted)]: [
    [ 'accept', '*/*' ],
    [ 'accept-encoding', 'gzip, deflate' ],
    [ 'accept-language', '*' ],
    [ 'cache-control', 'no-cache' ],
    [ 'connection', 'keep-alive' ],
    [ 'content-length', '0' ],
    [ 'host', 'localhost:3000' ],
    [ 'pragma', 'no-cache' ],
    [ 'sec-fetch-mode', 'cors' ],
    [ 'user-agent', 'undici' ]
  ]
}

另外,这就是我重定向到主页的方式:

const handleSubmit = async (e) => {
    e.preventDefault();

    if (email == "" || password == "") {
        toast.error("Fill all the fields");
        return;
    }

    const res = await fetch("api/auth/loginUser", {
        method: "POST",
        cache: "no-store",
        body: JSON.stringify({ email, password }),
    }).then((data) => data.json());

    if (res.success) {
        toast.success(res.message);
        router.push("/");  // <-------------redirect
    } else {
        toast.error(res.message);
    }
};

这就是 cookie 在边缘存储的方式: Image of cookie stored in the edge

authentication cookies http-headers middleware next.js13
1个回答
0
投票

您不能同时使用

export const dynamic = 'force-static'
和cookies()。根据此 NextJS 文档页面

通过强制

cookies()
headers()
useSearchParams()
返回空值来强制静态渲染并缓存布局或页面的数据。

唯一的解决方案是更改方法(也许使用

sessionStorage
来存储令牌?)或渲染为与
force-static
不同的东西。虽然我很清楚
force-static
在加载时间方面具有很大的优势(因为页面是完全静态的并且可以缓存),但是
headers()
cookies()
等的任何使用都是毫无意义的,因为空值将是回来了。

© www.soinside.com 2019 - 2024. All rights reserved.