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

IT技术 javascript reactjs next.js
2021-05-24 09:06:57

我正在尝试找出一种适当的身份验证方式,我知道这是GitHub 问题页面上的一个敏感主题

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

在我的server.js文件中,我有以下内容(注意-我正在使用nextjs learn 中的示例并添加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 的自定义路由。

有没有办法可以为每一个next/link没有通过快递的单张支票烘焙,以便我可以确保用户已登录?

3个回答

下一次聊天的蒂姆帮我解决了这个问题。可以在此处找到解决方案但我会引用他的话,以便大家可以看到:

我还创建了一个示例骨架模板,您可以查看一下。

——

编辑 20217 月- 警告:这是一个过时的解决方案,尚未确认可与最新版本的 next.js 一起使用。使用骨架模板风险自负。

随着 Next.js 12 的发布,现在有了对使用 Vercel Edge Functions 的中间件的 Beta 支持。

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

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

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

// pages/_middleware.js

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

JWT 身份验证示例

next.config.js

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

module.exports = withTM()

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())
}

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 })
  }
}

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.' } })
  }
}

有没有middleware在没有API的路线NextJS,但也有肝卵圆细胞,它可以用来连接数据库-选择用户,等: https://hoangvvo.com/blog/nextjs-middleware