Next.js中基于角色的身份验证

t3irkdon  于 2023-10-18  发布在  其他
关注(0)|答案(2)|浏览(142)

这是我的Next.js中间件。我想尝试使用中间件在Next.js中实现基于角色的身份验证。

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { Roles } from './types/role';
import {
  DASHBOARD_PATH,
  FORGOT_PASSWORD,
  LOGIN_PATH,
  RESET_PASSWORD,
  SET_TOKEN,
  WAIT_PATH,
} from './config/constants';

// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
  const token: any = request.cookies.get(SET_TOKEN)?.value;

  const ValidUserNotAllowed =
    request.nextUrl.pathname === LOGIN_PATH ||
    request.nextUrl.pathname === WAIT_PATH ||
    request.nextUrl.pathname === FORGOT_PASSWORD ||
    request.nextUrl.pathname === RESET_PASSWORD;
  if (ValidUserNotAllowed) {
    if (token) {
      const { role } = JSON.parse(token);
      if (role === Roles.user1) {
        return NextResponse.redirect(new URL(DASHBOARD_PATH.user1, request.url));
      } else if (role === Roles.user2) {
        return NextResponse.redirect(new URL(DASHBOARD_PATH.user2, request.url));
      } else if (role === Roles.user3) {
        return NextResponse.redirect(new URL(DASHBOARD_PATH.user3, request.url));
      }
    }
  } else {
    if (!token) {
      return NextResponse.redirect(new URL(LOGIN_PATH, request.url));
    }
  }
}
// See "Matching Paths" below to learn more
export const config = {
  matcher: [
    '/auth/login',
    '/user1/:path*',
    '/user2/:path*',
    '/auth/wait',
    '/user3/:path*',
    '/v1/:path*',
  ],
};

我试着其中之一。用户不能访问其他用户的路由,但在上面的代码中,用户可以访问其他用户的路由。

xdyibdwo

xdyibdwo1#

您当前的代码没有阻止用户访问其他角色的路由。
要根据用户角色限制对路由的访问,您需要对中间件进行一些修改。
查看下面的更新代码:

// This function can be marked `async` if using `await` inside
    export function middleware(request: NextRequest) {
      const token: any = request.cookies.get(SET_TOKEN)?.value;

      const ValidUserNotAllowed =
        request.nextUrl.pathname === LOGIN_PATH ||
        request.nextUrl.pathname === WAIT_PATH ||
        request.nextUrl.pathname === FORGOT_PASSWORD ||
        request.nextUrl.pathname === RESET_PASSWORD;

      if (ValidUserNotAllowed) {
        if (token) {
          const { role } = JSON.parse(token);
          if (role === Roles.user1 && request.nextUrl.pathname !== DASHBOARD_PATH.user1) {
            return NextResponse.redirect(new URL(DASHBOARD_PATH.user1, request.url));
          } else if (role === Roles.user2 && request.nextUrl.pathname !== DASHBOARD_PATH.user2) {
            return NextResponse.redirect(new URL(DASHBOARD_PATH.user2, request.url));
          } else if (role === Roles.user3 && request.nextUrl.pathname !== DASHBOARD_PATH.user3) {
            return NextResponse.redirect(new URL(DASHBOARD_PATH.user3, request.url));
          }
        }
      } else {
        if (!token) {
          return NextResponse.redirect(new URL(LOGIN_PATH, request.url));
        }
      }
    }
    // See "Matching Paths" below to learn more
    export const config = {
      matcher: [
        '/auth/login',
        '/auth/wait',
        '/v1/:path*',
        '/forgot-password',
        '/reset-password',
        '/user1/:path*',
        '/user2/:path*',
        '/user3/:path*',
      ],
    };
nwnhqdif

nwnhqdif2#

看起来你正在尝试使用中间件在Next.js中实现基于角色的身份验证。但是,根据提供的代码和说明,您的中间件逻辑中可能存在一些问题,这些问题可能允许用户访问其他用户的路由。
下面是一些改进中间件的建议:
1.使用白名单方式:您似乎使用了一种黑名单方法,在这种方法中,您显式地检查某些路径是否不允许有效用户使用。相反,您应该使用白名单方法,指定每个角色允许哪些路由。
1.处理无效路由:确保您有一个回退机制来处理无效路由,例如返回404页面或有意义的错误消息。
下面是一个例子,说明如何修改中间件以使用白名单方法:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { Roles } from './types/role';
import {
  DASHBOARD_PATH,
  LOGIN_PATH,
} from './config/constants';

export function middleware(request: NextRequest) {
  const token: any = request.cookies.get(SET_TOKEN)?.value;

  // Check if the user has a valid token
  if (!token) {
    return NextResponse.redirect(new URL(LOGIN_PATH, request.url));
  }

  const { role } = JSON.parse(token);

  // Define the allowed routes for each role
  const allowedRoutes = {
    [Roles.user1]: ['/user1', '/user1/dashboard'],
    [Roles.user2]: ['/user2', '/user2/dashboard'],
    [Roles.user3]: ['/user3', '/user3/dashboard'],
  };

  // Check if the current route is allowed for the user's role
  const currentPath = request.nextUrl.pathname;

  if (!allowedRoutes[role].some(allowedRoute => currentPath.startsWith(allowedRoute))) {
    // Redirect to an unauthorized page or handle it as you see fit
    return NextResponse.redirect(new URL('/unauthorized', request.url));
  }

  // If the user is allowed to access this route, continue
  return NextResponse.next();
}

在本例中,我们定义了一个allowedRoutes对象,将每个角色Map到一个允许的路由数组。然后检查当前路由是否在用户角色允许的路由内。如果没有,我们会将用户重定向到未经授权的页面。
确保您根据需要为/unauthorized和其他路径设置了相应的路由和页面。
另外,请确保正确导入了SET_TOKEN和其他必要的常量,因为在提供的代码片段中没有定义它们。

相关问题