如何使用 App Router 在 nextJS 14 中链接 kinde 身份验证检查中间件和 next-intl 中间件

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

我正在开发一个 Next.js 14 App Router 项目,我需要集成两个中间件: Kinde 身份验证中间件(用于受保护的路由,如 /dashboard)。 next-intl 中间件(用于 /en 或 /de 等路由上的国际化)。 由于 Next.js 仅支持单个中间件导出,因此我无法使用两个单独的中间件。这是我的代码的样子:

  1. next-intl 中间件:
import createMiddleware from 'next-intl/middleware';
import {routing} from '@/i18n/routing';

export default createMiddleware(routing);

export const config = {
    // Match only internationalized pathnames
    matcher: ['/', '/(en|fr|ar)/:path*']
};
  1. kinde withAuth 中间件:
import {
    authMiddleware,
    withAuth,
} from "@kinde-oss/kinde-auth-nextjs/middleware";

export default function middleware(req: Request) {
    return withAuth(req);
}

export const config = {
    matcher: ["/dashboard"],
};

我考虑在同一个文件中调用两个中间件函数,但我不确定如何正确构建逻辑来处理身份验证和国际化。

oauth middleware next.js13 next-intl kinde
1个回答
0
投票

创建一个名为

middlewares
的文件夹,其中包含以下文件:

  1. i18n中间件:

import {
    NextResponse,
    type NextFetchEvent,
    type NextRequest
} from 'next/server'
import { CustomMiddleware } from './chain'
import createMiddleware from "next-intl/middleware";
import {routing} from "@/i18n/routing";

export function withI18nMiddleware(middleware: CustomMiddleware) {
    return async (request: NextRequest, event: NextFetchEvent) => {
        // The first middleware in the chain has to create the response

        // Internationalisation with next-intl middleware
        const handleI18nRouting = createMiddleware(routing);
        console.log("middleware ai18n called")
        let response = NextResponse.next()
        try {
            response = handleI18nRouting(request)
        }catch (e){
            console.log("error in i18n middleware", e)
        }

        // Call the next middleware and pass the request and response
        return middleware(request, event, response)
    }
}

  1. authmiddleware.ts:

import {
    NextResponse,
    type NextFetchEvent,
    type NextRequest
} from 'next/server'

import { CustomMiddleware } from './chain'
import {
    authMiddleware,
    withAuth,
} from "@kinde-oss/kinde-auth-nextjs/middleware";

export function withAuthMiddleware(middleware: CustomMiddleware) {
    return async (
        request: NextRequest,
        event: NextFetchEvent,
        response: NextResponse
    ) => {

        // Check the authentication using Kinde-Auth middleware
        const protectedRoutes = ['/dashboard', '/en/dashboard', '/fr/dashboard', '/ar/dashboard'];
        const isProtectedRoute = protectedRoutes.some(route => request.nextUrl.pathname.startsWith(route));
        if (isProtectedRoute) {
            console.log("middleware auth called")
            return withAuth(request);
        }else {
            // Call the next middleware and pass the request and response
            return middleware(request, event, response)
        }


    }
}

  1. 链.ts:

import { NextMiddlewareResult } from 'next/dist/server/web/types'
import { NextResponse } from 'next/server'
import type { NextFetchEvent, NextRequest } from 'next/server'

export type CustomMiddleware = (
    request: NextRequest,
    event: NextFetchEvent,
    response: NextResponse
) => NextMiddlewareResult | Promise<NextMiddlewareResult>

type MiddlewareFactory = (middleware: CustomMiddleware) => CustomMiddleware

export function chain(
    functions: MiddlewareFactory[],
    index = 0
): CustomMiddleware {
    const current = functions[index]
    console.log("middleware called")
    if (current) {
        const next = chain(functions, index + 1)
        return current(next)
    }

    return (
        request: NextRequest,
        event: NextFetchEvent,
        response: NextResponse
    ) => {
        return response
    }
}

然后在middlware.ts里面放入代码:

import { chain } from '@/middlewares/chain'
import {withI18nMiddleware} from "@/middlewares/i18nMiddleware";
import {withAuthMiddleware} from "@/middlewares/authMiddleware";


const middlewares = [ withI18nMiddleware, withAuthMiddleware]
export default chain(middlewares)

export const config = {
    // Match only internationalized pathnames
    matcher: ['/', '/(en|fr|ar)/:path*']
};

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