nextjs 路由中间件进行身份验证
Posted
技术标签:
【中文标题】nextjs 路由中间件进行身份验证【英文标题】:nextjs route middleware for authentication 【发布时间】:2018-12-27 19:18:13 【问题描述】:我正在尝试找出一种适当的身份验证方式,我知道这是GitHub issue page 上的一个敏感主题。
我的身份验证很简单。我在会话中存储了一个 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/link
href 去那里,它不会。我认为这是因为此时它没有使用 express,而是使用 next 的自定义路由。
有没有一种方法可以为每个未通过 express 的next/link
进行检查,以便确保用户已登录?
【问题讨论】:
【参考方案1】:下一次聊天的 Tim 帮我解决了这个问题。解决方案可以在here 找到,但我会引用他的内容,以便大家看到:
您可以在_app.js
getInitialProps
和redirect like this 进行检查
Example of how to use it
_app.js documentation
我还创建了一个example skeleton template,你可以看看。
--
2021 年 7 月编辑 - 警告:这是一个过时的解决方案,尚未确认可与最新版本的 next.js 一起使用。使用骨架模板需要您自担风险。
【讨论】:
所有链接都已失效 :(【参考方案2】:随着 Next.js 12 的发布,现在使用 Vercel Edge Functions 对中间件提供了 beta 支持。
https://nextjs.org/blog/next-12#introducing-middleware
中间件使用严格的运行时支持标准 Web API,例如 fetch。 > 这在使用 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在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.' )
【讨论】:
【参考方案3】:middleware
中没有 API 路由,NextJS
中没有 middleware
,但是有 HOC,您可以使用它来连接到 db - 选择用户等:
https://hoangvvo.com/blog/nextjs-middleware
【讨论】:
以上是关于nextjs 路由中间件进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章
任何想法如何使用 vue js 和 vue 路由器在 laravel 5.3 中进行基于会话的身份验证