我不想向某些外部请求或 OAuth 添加身份验证。只需对节点服务器进行服务器端基本身份验证。
截至编写 Next.js 似乎不支持它:https ://github.com/vercel/next.js/discussions/17719
它支持身份验证,但我想它必须添加到应用程序的每个路由中: https: //nextjs.org/docs/authentication
Su-*_*ang 11
--- 更新为 NextJS 12.2 ---
Nextjs 的当前版本允许您通过在目录(pages 文件夹旁边)中添加一个middleware.js/ts文件来运行添加自定义中间件。root在那里,您可以简单地检查 Auth-headers 并决定调用next以允许它或返回 401 状态代码以拒绝它。这是从 Nextjs 示例(打字稿)复制的示例
import { NextRequest, NextResponse } from 'next/server'
export const config = {
matcher: '/',
}
export function middleware(req: NextRequest) {
const basicAuth = req.headers.get('authorization')
const url = req.nextUrl
if (basicAuth) {
const authValue = basicAuth.split(' ')[1]
const [user, pwd] = atob(authValue).split(':')
if (user === '4dmin' && pwd === 'testpwd123') {
return NextResponse.next()
}
}
url.pathname = '/api/auth'
return NextResponse.rewrite(url)
}
Run Code Online (Sandbox Code Playgroud)
这是完整示例项目的链接: https://github.com/vercel/examples/tree/main/edge-functions/basic-auth-password
--- 对于旧版本(12.2 之前)---
_middleware.js/ts当前版本的 Nextjs 允许您通过目录中的文件来运行添加自定义中间件pages。在那里,您可以简单地检查 Auth-headers 并决定调用next以允许它或返回 401 状态代码以拒绝它。这是从 Nextjs 示例(打字稿)复制的示例
import { NextRequest, NextResponse } from 'next/server'
export function middleware(req: NextRequest) {
const basicAuth = req.headers.get('authorization')
if (basicAuth) {
const auth = basicAuth.split(' ')[1]
const [user, pwd] = Buffer.from(auth, 'base64').toString().split(':')
if (user === '4dmin' && pwd === 'testpwd123') {
return NextResponse.next()
}
}
return new Response('Auth required', {
status: 401,
headers: {
'WWW-Authenticate': 'Basic realm="Secure Area"',
},
})
}
Run Code Online (Sandbox Code Playgroud)
这是完整示例项目的链接: https://github.com/vercel/examples/tree/main/edge-functions/basic-auth-password
编辑:如果您想将其托管在 Vercel 上,那么下面的 ExpressJs 解决方案将无法工作,例如,它的成本有点高,但提供了最好的 Next.js 托管,具有内置边缘缓存以及图像缩放和优化功能。因此,如果您想将其托管在 Vercel 上,则可以使用以下方式向每个路由添加身份验证: https: //nextjs.org/docs/authentication(除非从项目一开始就完成,否则可能会很麻烦)。
然而,如果您打算将其托管在支持 Node.js 和 Express.js 托管的其他地方(并且没有为 Next.js 提供任何特殊功能),那么下面的解决方案是一个很好的解决方案。
本文不涉及基本身份验证凭据的存储或使用多个凭据。这更像是一个起点,因为我在谷歌上根本找不到任何东西。
在下面的两个示例中,我们将使用 Express.js 来托管 NextJS(在生产模式下!)。
在两个示例中启动服务器:(node index.mjs当前使用node -v 14.9.0)
首先:index.mjs在根目录中创建文件。
(选项 1)使用最新的 NextJS:
import next from 'next'
import express from 'express'
import auth from 'basic-auth'
const dev = process.env.NODE_ENV === 'development'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
server.use(function (req, res, next) {
const credentials = auth(req)
if (!credentials || credentials.name !== '[change_me_username]' || credentials.pass !== '[change_me_password]') {
res.status(401)
res.header('WWW-Authenticate', 'Basic realm="example"')
res.send('Access denied')
} else {
next()
}
});
server.get('*', (req, res) => {
return handle(req, res)
})
const port = 80;
server.listen(port, (err) => {
if (err) {
throw err
}
console.log(`Ready on http://localhost:${port}`)
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})
Run Code Online (Sandbox Code Playgroud)
(选项2)使用NextJS 9.4(如果无法升级)
此答案不涉及潜在 CSP 安全整体的潜在后果,处理该问题的最佳且最简单的方法是升级到 NextJs 9.5 版本。
import next from 'next'
import express from 'express'
import auth from 'basic-auth'
const dev = process.env.NODE_ENV === 'development'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
server.use(function (req, res, next) {
const credentials = auth(req)
if (!credentials || credentials.name !== '[change_me_username]' || credentials.pass !== '[change_me_password]') {
res.status(401)
res.header('WWW-Authenticate', 'Basic realm="example"')
res.send('Access denied')
} else {
// this is different from above NextJS 9.5, 9.4 requires inline js.
res.setHeader(
'Content-Security-Policy',
"default-src * 'self' data: 'unsafe-inline' *"
);
next()
}
});
server.get('*', (req, res) => {
return handle(req, res)
})
const port = 80;
server.listen(port, (err) => {
if (err) {
throw err
}
console.log(`Ready on http://localhost:${port}`)
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})
Run Code Online (Sandbox Code Playgroud)
next.config.js如果您使用,则在里面next-images,否则只需放置对象:module.exports = { // ... }const withImages = require('next-images')
module.exports = withImages({
async headers() {
return [
{
source: '/:path*',
headers: [
{
// // https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
key: 'Content-Security-Policy',
value: "default-src * 'self' data: 'unsafe-inline' *"
}
]
}
]
}
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10352 次 |
| 最近记录: |