nextjs 用于身份验证的路由中间件

2023-12-27

我正在尝试找出一种适当的身份验证方法,我知道这是一个敏感的话题GitHub 问题页面 https://github.com/zeit/next.js/issues/153.

我的身份验证很简单。我在会话中存储 JWT 令牌。我将其发送到不同的服务器以供批准。如果我返回 true,我们继续前进,如果我返回 false,它会清除会话并将它们发送到主页。

In my server.js文件我有以下内容(注意-我使用的示例来自下一个学习 https://nextjs.org/learn/basics/create-dynamic-pages只需添加isAuthenticated):

function isAuthenticated(req, res, next) {
  //checks go here

  //if (req.user.authenticated)
   // return next();

  // IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
  res.redirect('/');
}

server.get('/p/:id', isAuthenticated, (req, res) => {
  const actualPage = '/post'
  const queryParams = { id: req.params.id }
  app.render(req, res, actualPage, queryParams)
})

这按设计工作。如果我刷新页面/p/123,它将重定向到/。但是,如果我通过next/linkhref,没有。我相信这是因为它此时不使用 Express,而是使用自定义路由。

有没有办法让我为每一个人都开一张支票next/link不通过快递,以便我可以确保用户已登录?


Edit:Next 12.2+ 的更新答案

注意:以下内容是从官方博客文章复制的,因为 SO 通常不鼓励随着时间的推移而变得陈旧/失效的链接https://nextjs.org/blog/next-12-2#middleware-stable https://nextjs.org/blog/next-12-2#middleware-stable

中间件现已稳定在 12.2 中,并根据用户反馈改进了 API。

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

// If the incoming request has the "beta" cookie
// then we'll rewrite the request to /beta
export function middleware(req: NextRequest) {
  const isInBeta = JSON.parse(req.cookies.get('beta') || 'false');
  req.nextUrl.pathname = isInBeta ? '/beta' : '/';
  return NextResponse.rewrite(req.nextUrl);
}

// Supports both a single value or an array of matches
export const config = {
  matcher: '/',
};

迁移指南

https://nextjs.org/docs/messages/middleware-upgrade-guide https://nextjs.org/docs/messages/middleware-upgrade-guide重大变化

  • 无嵌套中间件
  • 无响应体
  • Cookie API 已改进
  • 新的用户代理助手
  • 不再有页面匹配数据
  • 对内部 Next.js 请求执行中间件

如何升级

你应该声明一个中间件文件在您的应用程序中,它应该位于pages目录和命名without an _字首。您的中间件文件仍然可以有.ts or .js扩大。

中间件将被调用应用程序中的每条路线,并且可以使用自定义匹配器来定义匹配过滤器。以下是触发的中间件示例/about/* and /dashboard/:path*,自定义匹配器在导出的配置对象中定义:

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  return NextResponse.rewrite(new URL('/about-2', request.url))
}

// Supports both a single string value or an array of matchers
export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
}

Edit:下一个 > 12 和

随着 Next.js 12 的发布,现在对使用 Vercel Edge Functions 的中间件提供了测试版支持。

https://nextjs.org/blog/next-12#introducing-middleware https://nextjs.org/blog/next-12#introducing-middleware

中间件使用严格的运行时,支持 fetch 等标准 Web API。 > 使用 next start 即可开箱即用,也可在 Vercel 等使用 Edge Functions 的 Edge 平台上使用。

要在Next.js中使用中间件,您可以创建文件pages/_middleware.js。在此示例中,我们使用标准 Web API 响应 (MDN):

// pages/_middleware.js

export function middleware(req, ev) {
  return new Response('Hello, world!')
}

JWT 身份验证示例

  • https://github.com/vercel/examples/tree/main/edge-functions/jwt-authentication https://github.com/vercel/examples/tree/main/edge-functions/jwt-authentication

in next.config.js:

const withTM = require('@vercel/edge-functions-ui/transpile')()

module.exports = withTM()

in pages/_middleware.js:

import { NextRequest, NextResponse } from 'next/server'
import { setUserCookie } from '@lib/auth'

export function middleware(req: NextRequest) {
  // Add the user token to the response
  return setUserCookie(req, NextResponse.next())
}

in pages/api/_middleware.js:

import type { NextRequest } from 'next/server'
import { nanoid } from 'nanoid'
import { verifyAuth } from '@lib/auth'
import { jsonResponse } from '@lib/utils'

export async function middleware(req: NextRequest) {
  const url = req.nextUrl

  if (url.searchParams.has('edge')) {
    const resOrPayload = await verifyAuth(req)

    return resOrPayload instanceof Response
      ? resOrPayload
      : jsonResponse(200, { nanoid: nanoid(), jwtID: resOrPayload.jti })
  }
}

in pages/api/index.js:

import type { NextApiRequest, NextApiResponse } from 'next'
import { verify, JwtPayload } from 'jsonwebtoken'
import { nanoid } from 'nanoid'
import { USER_TOKEN, JWT_SECRET_KEY } from '@lib/constants'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== 'GET') {
    return res.status(405).json({
      error: { message: 'Method not allowed' },
    })
  }
  try {
    const token = req.cookies[USER_TOKEN]
    const payload = verify(token, JWT_SECRET_KEY) as JwtPayload
    res.status(200).json({ nanoid: nanoid(), jwtID: payload.jti })
  } catch (err) {
    res.status(401).json({ error: { message: 'Your token has expired.' } })
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nextjs 用于身份验证的路由中间件 的相关文章

随机推荐