因此,我为 Next.js 寻找了一些不需要在服务器端进行任何工作的身份验证选项。我的目标是阻止用户在没有密码的情况下进入网站。
我已经使用 NextAuth 设置了一些测试(经过几次其他尝试),显然我可以使用会话和 cookie 阻止页面,但经过几个小时的研究,我仍然找不到如何阻止资产(例如/public 文件夹中的 /image.png)来自未经身份验证的请求。
如果没有自定义服务器,这甚至可能吗?我在这里缺少一些核心理解吗?
提前致谢。
因此,我为 Next.js 寻找了一些不需要在服务器端进行任何工作的身份验证选项。我的目标是阻止用户在没有密码的情况下进入网站。
我已经使用 NextAuth 设置了一些测试(经过几次其他尝试),显然我可以使用会话和 cookie 阻止页面,但经过几个小时的研究,我仍然找不到如何阻止资产(例如/public 文件夹中的 /image.png)来自未经身份验证的请求。
如果没有自定义服务器,这甚至可能吗?我在这里缺少一些核心理解吗?
提前致谢。
我也偶然发现了这个问题。我的笨蛋花了一段时间,但最后我想通了。
正如你所说 - 对于身份验证,你可以使用任何东西。比如 NextAuth。
对于文件服务:我设置了新的 api 端点并使用了 NodeJS 的魔法来获取文件并在管道中提供它。这与您在 Express 中所做的非常相似。不要忘记在您的回复中设置正确的头部信息。
这是要演示的小片段(打字稿版本):
import { NextApiRequest, NextApiResponse } from 'next'
import {stat} from "fs/promises"
import {createReadStream, existsSync} from "fs"
import path from "path"
import mime from "mime"
//basic nextjs api
export default async function getFile (req: NextApiRequest, res: NextApiResponse) {
// Dont forget to auth first!1!!!
// for this i created folder in root folder (at same level as normal nextjs "public" folder) and the "somefile.png" is in it
const someFilePath = path.resolve('./private/somefile.png');
// if file is not located in specified folder then stop and end with 404
if (! existsSync(someFilePath)) return res.status(404);
// Create read stream from path and now its ready to serve to client
const file = createReadStream(path.resolve('./private/somefile.png'))
// set cache so its proper cached. not necessary
// 'private' part means that it should be cached by an invidual(= is intended for single user) and not by single cache. More about in https://stackoverflow.com/questions/12908766/what-is-cache-control-private#answer-49637255
res.setHeader('Cache-Control', `private, max-age=5000`);
// set size header so browser knows how large the file really is
// im using native fs/promise#stat here since theres nothing special about it. no need to be using external pckages
const stats = await stat(someFilePath);
res.setHeader('Content-Length', stats.size);
// set mime type. in case a browser cant really determine what file its gettin
// you can get mime type by lot if varieties of methods but this working so yay
const mimetype = mime.getType(someFilePath);
res.setHeader('Content-type', mimetype);
// Pipe it to the client - with "res" that has been given
file.pipe(res);
}