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

Next.js App Router登录提交后router.push失效及回退异常求助

Next.js App Router 登录跳转与Middleware校验异常问题

问题背景

我基于Next.js App Router开发项目,已通过Middleware实现access token的校验逻辑:

  • 用户无token时,访问根路径(/)及登录相关页面以外的页面,会自动携带returnURL参数跳转到登录页,登录完成后应跳转回原页面,但该逻辑未正常工作。
  • 登录流程采用react-hook-form结合tanstack-query的useMutation实现。

现有代码

登录组件核心代码

const returnURL = useSearchParams().get('returnURL') || '/';

// 提交处理函数
const onSubmit: SubmitHandler<FieldValues> = () => {
  postSigninMutate(
    { username: payload.username, password: payload.password },
    {
      onSuccess: async (res) => {
        const { response } = res;
        const authorizationToken = response.headers.get('authorization-token');
        const expiresAt = response.headers.get('authorization-token-expired-at');
        const refreshToken = response.headers.get('refresh-token');

        if (authorizationToken && expiresAt && refreshToken) {
          Cookies.set('authorization-token', authorizationToken, { secure: true });
          Cookies.set('expires-at', expiresAt);
          Cookies.set('refresh-token', refreshToken, { secure: true });
        }

        router.push(returnURL);
      },
      onError: (err) => alert(err)
    }
  );
};

<form onSubmit={handleSubmit(onSubmit)} className="flex-col-start m-0 w-80 gap-6 pt-10">
...

Middleware代码(middleware.ts)

import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  const url = request.nextUrl.pathname;
  const accessToken = request.cookies.get('authorization-token');

  console.log(accessToken ? 'yes' : 'no');
  console.log(url);

  if (url === '/') {
    const response = NextResponse.next();
    response.headers.set('X-Skip-Icons', 'true');
    return response;
  }

  if (
    accessToken &&
    (url === '/signup' ||
      url === '/login' ||
      url === '/kakaoLogin' ||
      url === '/find-password-email' ||
      url === '/find-password-question' ||
      url === '/find-password-newpassword')
  ) {
    if (request.nextUrl.searchParams.has('returnURL')) {
      return NextResponse.redirect(new URL(request.nextUrl.searchParams.get('returnURL') || '/', request.url));
    }
    console.log('here');
    return NextResponse.redirect(new URL('/', request.url));
  }

  if (
    !accessToken &&
    url !== '/signup' &&
    url !== '/login' &&
    url !== '/kakaoLogin' &&
    url !== '/find-password-email' &&
    url !== '/find-password-question' &&
    url !== '/find-password-newpassword'
  ) {
    const redirectURL = new URL('/login', request.url);
    const returnURL = request.nextUrl.pathname + request.nextUrl.search;
    redirectURL.searchParams.set('returnURL', returnURL);

    const response = NextResponse.redirect(redirectURL);
    return response;
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico|icons/favicon.ico|icon).*)']
};

临时解决方案与疑问

我怀疑问题源于页面缓存、客户端与服务器的cookie更新不同步。尝试在登录成功后调用router.refresh(),此时Middleware会触发、页面也会更新,但地址栏URL没有变化。之后我添加了setTimeout延迟执行router.push(returnURL),虽然能实现跳转,但不确定这是不是正确的解决方案:

router.refresh();
setTimeout(() => {
  router.push(returnURL);
}, 1000);

额外问题

登录成功后,按浏览器返回键仍能回到登录页,不符合预期。

内容的提问来源于stack exchange,提问作者ayoung

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 07:58:15