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

Next.js中间件路由重写问题:登录后跳转失效求助

解决Next.js中间件rewrite导致登录后跳转失效的问题

核心问题在于NextResponse.rewrite是服务器端内容重写,但浏览器地址栏URL保持不变,这会让浏览器误以为当前仍在原路径(比如/customer/cart),导致登录后执行router.push('/customer/account')时跳转失效。改用NextResponse.redirect即可解决,它会触发浏览器的URL跳转,同时我们还可以添加回调参数,让用户登录后回到原本想要访问的页面。

原代码的问题点

  1. 使用rewrite而非redirect,导致URL不更新
  2. 存在错误逻辑:已登录客户访问购物车时,会被强制重写成账户页面,破坏正常路由

修改后的完整middleware.ts代码

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { getDataFromToken } from './helpers/auth'

export async function middleware(request: NextRequest) {
    const path = request.nextUrl.pathname
    const token = request.cookies.get('token')?.value || ''
    const userData = await getDataFromToken(request)

    // 管理员路径校验:未登录或非管理员,跳转登录页并携带回调地址
    const isAdminPath = path.startsWith('/admin')
    if (isAdminPath && (!token || userData?.role !== 'admin')) {
        const loginUrl = new URL('/auth/login', request.url)
        loginUrl.searchParams.set('callbackUrl', encodeURIComponent(path))
        return NextResponse.redirect(loginUrl)
    }

    // 客户专属路径校验(账户/购物车)
    const isCustomerProtectedPath = path.startsWith('/customer/account') || path.startsWith('/customer/cart')
    if (isCustomerProtectedPath) {
        // 未登录或非客户角色,跳转登录页并携带回调地址
        if (!token || userData?.role !== 'customer') {
            const loginUrl = new URL('/auth/login', request.url)
            loginUrl.searchParams.set('callbackUrl', encodeURIComponent(path))
            return NextResponse.redirect(loginUrl)
        }
        // 已登录且为客户,直接放行
    }
}

export const config = {
    matcher: [
        '/customer/account', 
        '/customer/cart',
        '/admin',
    ],
}

关键修改说明

  • 替换rewrite为redirect:NextResponse.redirect会更新浏览器地址栏URL,彻底解决登录后router.push失效的问题
  • 添加callbackUrl参数:将用户原本访问的路径编码后作为参数传递给登录页,登录成功后可以跳回该路径,提升用户体验
  • 删除错误重写逻辑:移除原代码中强制将客户路径重写到账户页面的逻辑,让已登录客户正常访问自己的专属路径

登录页配套处理

在登录组件中,登录成功后读取callbackUrl参数,跳回用户原本想要访问的页面:

// 登录成功后的逻辑示例
const handleLoginSuccess = async () => {
    // ... 执行登录请求及token存储逻辑
    const searchParams = new URLSearchParams(window.location.search)
    const callbackUrl = searchParams.get('callbackUrl')
    // 优先跳回原路径,否则默认跳客户账户页
    router.push(callbackUrl || '/customer/account')
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:35:55