4

因此,我为 Next.js 寻找了一些不需要在服务器端进行任何工作的身份验证选项。我的目标是阻止用户在没有密码的情况下进入网站。

我已经使用 NextAuth 设置了一些测试(经过几次其他尝试),显然我可以使用会话和 cookie 阻止页面,但经过几个小时的研究,我仍然找不到如何阻止资产(例如/public 文件夹中的 /image.png)来自未经身份验证的请求。

如果没有自定义服务器,这甚至可能吗?我在这里缺少一些核心理解吗?

提前致谢。

4

1 回答 1

3

我也偶然发现了这个问题。我的笨蛋花了一段时间,但最后我想通了。

正如你所说 - 对于身份验证,你可以使用任何东西。比如 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);
}
干杯

于 2021-04-06T17:47:06.813 回答