【问题标题】:Authentication to serve static files on Next.js?在 Next.js 上提供静态文件的身份验证?
【发布时间】:2021-05-31 09:35:36
【问题描述】:

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

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

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

提前致谢。

【问题讨论】:

    标签: reactjs authentication next.js next-auth


    【解决方案1】:

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

    正如你所说 - 对于身份验证,你可以使用任何东西。比如 NextAuth。

    对于文件服务:我设置了新的 api 端点并使用 NodeJS 获取文件并在管道中提供文件的魔法。这与您在 Express 中所做的非常相似。不要忘记在您的回复中设置正确的头部信息。

    这里有小sn-p来演示(打字稿版本):

    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://*.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);
    }
    干杯

    【讨论】: