NextJS如何禁止指定目录访问并仅向已登录用户提供图片服务
NextJS 实现私有图片资源访问方案
第一步:调整敏感图片存放位置
NextJS 中/public目录下的所有资源默认会作为静态资源公开访问,无法直接通过业务逻辑禁止访问,因此优先建议将需要鉴权的图片移出/public目录,你可以在项目根目录新建一个非公开的存放目录,例如private_images/,该目录不会被直接对外暴露,从根源上避免用户直接访问到原始图片。
第二步:拦截公开目录的非法访问
如果你确实需要保留图片在/public/images下,可以通过根目录的middleware.ts匹配对应路径的请求,直接拦截未登录用户的访问:
import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { // 匹配所有/public/images下的请求 if (request.nextUrl.pathname.startsWith('/images/')) { // 这里替换为你自己的登录态校验逻辑,例如校验cookie里的token、session等 const isLogin = request.cookies.has('user_token') if (!isLogin) { return new NextResponse('禁止访问', { status: 403 }) } } } export const config = { matcher: '/images/:path*', }
第三步:完善带鉴权的图片API路由
Pages Router 版本(适配你现有的写法)
你现有的API路由逻辑可以补充鉴权逻辑,建议做成动态路由适配不同图片,示例如下:
// pages/api/image/[name].js export default async function handler(req, res) { // 先做登录态校验,替换为你自己的业务校验逻辑 const isLogin = req.cookies.user_token if (!isLogin) { return res.status(403).send('禁止访问') } const { name } = req.query res.setHeader('Content-Type', 'image/jpg') // 可以读取本地private_images下的文件,或者请求内部存储的图片资源 const imageBuffer = await (await fetch(`http://内部存储地址/images/${name}.jpg`)).body res.send(imageBuffer) }
对应Image组件用法:
<Image src={`/api/image/logo`} alt="Logo" width={720} height={160} />
App Router 版本
如果使用NextJS13+的App Router,可以用Route Handler实现相同逻辑:
// app/api/image/[name]/route.ts import { NextResponse } from 'next/server' import { cookies } from 'next/headers' export async function GET(request: Request, { params }: { params: { name: string } }) { const cookieStore = cookies() const isLogin = cookieStore.has('user_token') if (!isLogin) { return new NextResponse('禁止访问', { status: 403 }) } const res = await fetch(`http://内部存储地址/images/${params.name}.jpg`) const imageBuffer = await res.arrayBuffer() return new NextResponse(imageBuffer, { headers: { 'Content-Type': 'image/jpg', }, }) }
额外说明
- 所有私有图片访问都走封装的API路由即可实现和PHP相同的鉴权效果,不要将私有图片的实际存储地址对外暴露
- 如果使用云存储存储图片,可以配合生成带过期时间的签名URL,安全性更高
内容的提问来源于stack exchange,提问作者Petr Marek
相关产品推荐
相关产品推荐

