这是我第一次在这里发帖,但我搜索了很多链接和论坛,从来没有找到一个适合我的答案…我在cookie中保存了一个jwt,并在nextjs中使用了一个中间件来检查用户是否经过了很好的身份验证,以及它的令牌是否尚未过期。我的问题是Next JS自动兑现所有页面,所以当我去例如“/home/chat”,中间件被触发,路由是安全的,用户可以访问页面,只有当他连接,但如果我回到这个页面,它已经兑现,所以它永远不会再次触发中间件,所以用户可以访问它,即使它的令牌不再有效,它会导致一些问题。我在文档中添加了“export const dynamic = 'force-dynamic'”或“export const revalidate = 0”,但它们是一样的。此外,我在文档中看到,使用cookie()函数会自动将页面置于动态状态,但无论我做什么,中间件都不会再次触发,甚至页面中的console.log()也只会第一次触发,不会再次触发。这是我的“/home/chat”页面:
import { cookies } from "next/headers";
import Link from "next/link";
import styles from "@/styles/chatPage/ChatPage.module.css";
import ChatClient from "@/components/chatPage/ChatClient";
import Profile_Service from "@/services/Profile.service";
export default async function ChatPage() {
let token: string | undefined;
let myself: Profile & { avatar: Avatar };
console.log("chat page");
try {
token = cookies().get("crunchy-token")?.value;
if (!token)
throw new Error("No token value");
const profilService = new Profile_Service(token);
myself = await profilService.getProfileAndAvatar();
} catch (err) {
console.log(err);
return (
<div className={styles.error}>
<h2>Oops... Something went wrong!</h2>
<Link href={"/home"} className={styles.errorLink}>
<p>Return to Home Page!</p>
</Link>
</div>
)
}
return (
<ChatClient token={token} myself={myself}/>
)
}
字符串
谢谢你花时间阅读我和任何帮助!
所以我看到之前我们必须使用gerServerSideProps函数,但这是在下一个13的应用程序目录之前。我看到了这个文档“很高兴知道:cookie()是一个动态函数,其返回值无法提前知道。在布局或页面中使用它将在请求时选择动态呈现的路线。“但它仍然不是动态的,我不知道这是一个错误还是我还不明白的东西。也许这是我不明白的东西,但当我说它仍然不是动态的,我的意思是,console.log和中间件中的其他功能被触发,例如,我第一次去聊天页面。然后当我回来的时候,中间件中没有日志和动作。。
我所期望的是在访问每个页面之前通过这个中间件:
import { verifyAuth } from "@/lib/auth/auth";
import { NextRequest, NextResponse } from "next/server";
export async function middleware(req: NextRequest) {
const crunchyToken = req.cookies.get("crunchy-token")?.value;
const verifiedToken =
crunchyToken &&
(await verifyAuth(crunchyToken).catch((err) => {
console.log(err);
}));
const url = req.nextUrl;
console.log(verifiedToken, url);
if (
verifiedToken &&
verifiedToken.login &&
req.nextUrl.pathname === "/home/create"
) {
return NextResponse.redirect(new URL("/home", req.url));
}
if (
verifiedToken &&
!verifiedToken.login &&
req.nextUrl.pathname.startsWith("/home") &&
req.nextUrl.pathname !== "/home/create"
) {
return NextResponse.redirect(new URL("/home/create", req.url));
}
if (req.nextUrl.pathname === "/" && !verifiedToken) {
return NextResponse.redirect(new URL("/welcome", req.url));
}
if (req.nextUrl.pathname === "/" && verifiedToken) {
return NextResponse.redirect(new URL("/home", req.url));
}
if (req.nextUrl.pathname.startsWith("/welcome") && verifiedToken) {
return NextResponse.redirect(new URL("/home", req.url));
}
if (req.nextUrl.pathname.startsWith("/home") && !verifiedToken) {
return NextResponse.redirect(new URL("/welcome", req.url));
}
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - icon, images
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
'/((?!api|icon|images|_next/static|_next/image|favicon.ico).*)',
],
};
型
该中间件的目的是获取令牌,验证它,并允许人们访问受限页面或将其重定向到身份验证页面。
第一次编辑:非常感谢您的帮助,现在我希望我的中间件每次都被触发,但我的服务器组件也被触发,因为它们在cookie中获取用户数据及其令牌。正如我在文档中所说,如果我使用cookie()函数,它将是动态的,但现在它们在开始时被编译,并且永远不会再次运行。
下面是我的verifyAuth函数:
import { jwtVerify} from "jose";
export const verifyAuth = async (token: string) => {
try {
const verified = await jwtVerify(
token,
new TextEncoder().encode(process.env.JWT_SECRET),
);
return verified.payload;
} catch (error) {
throw new Error('Your token has expired');
}
}
型
除此之外,
console.log(“ChatPage”)
在聊天页面上的服务器端记录只是我第一次去这个页面例如,即使它需要得到的饼干.我发现的一个解决方案是将此客户端组件添加到服务器组件中:
// Sample Refresher Component
// to be imported into SSR page
// needing a refresh after
// next.js appDir Link nav
//
'use client'
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
export function Refresher() {
const router = useRouter()
useEffect(() => {
router.refresh()
}, [router])
return <></>
}
型
这是一个非常丑陋的方法,我不想这样做,因为我目前正在编写一个单页应用程序,但这是我发现的唯一方法,在第一次访问我的页面之前运行中间件。
有人能帮帮我吗?
1条答案
按热度按时间h22fl7wq1#
是的,Next.js确实会在第一次访问时缓存页面。这意味着返回到它本质上不会重新运行中间件。
但是,如果刷新页面,则会强制重新呈现页面,从而重新运行中间件;你可以使用console.logs来检查正在运行的中间件。
中间件将100%运行在
config
下的任何路由上,所以问题一定出在令牌逻辑或条件上。请提供您的
verifyAuth
代码,因为问题可能就在那里。