编辑:如果您想在 Vercel 上托管下面的 ExpressJs 解决方案将不起作用,例如,它会花费一些成本,但可以提供带有内置边缘缓存和图像的最佳 Next.js 托管缩放和优化。因此,如果您想在 Vercel 上托管它而不是使用:https://nextjs.org/docs/authentication 为每条路由添加身份验证(除非从项目开始就完成)。
如果您打算将它托管在支持 Node.js 和 Express.js 托管的其他地方(并且没有为 Next.js 提供任何特殊功能),那么以下是一个很好的解决方案。
ExpressJs 解决方案:
这篇文章不涉及存储基本身份验证凭据或使用多个凭据。这更像是一个起点,因为我在 google 上根本找不到任何东西。
在下面的两个示例中,我们将使用 Express.js 来托管 NextJS(处于生产模式!)。
在两个示例中启动服务器:node index.mjs(当前使用 node -v 14.9.0)
首先:在根目录下创建index.mjs文件。
(选项 1)使用最新的 NextJS:
- 使用 latest(撰写时为 9.5)NextJS + Express.js 节点服务器(最新的 nextjs 已修复问题(我尚未验证) 与 CSP
https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
- 在 index.mjs 中添加以下代码(安装所需模块):
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)
})
(选项 2)使用 NextJS 9.4(如果无法升级)
此答案不涉及潜在 CSP 安全整体的潜在后果,最好和最简单的处理方法是升级到 NextJs 9.5 期间。
- 在 index.mjs 中添加以下代码(安装所需模块):
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)
})
- 在
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' *"
}
]
}
]
}
})