如何在NextJS中展示受Authorization Header保护的图片?
问题根源
浏览器原生<img>标签发起的请求无法自定义Authorization头;而你代码中设置的mode: 'no-cors'会强制浏览器忽略所有自定义请求头(包括Authorization),导致请求始终未授权,返回401错误。
可行解决方案
方案一:用NextJS API路由做代理(推荐,适配SSR场景)
利用服务端请求不受浏览器CORS限制、可正常携带Authorization头的特性,创建一个API路由作为中间层转发图片请求,前端直接请求这个路由即可。
- 创建API路由(App Router示例)
在app/api/proxy-image/route.js中写入:
import { NextResponse } from 'next/server'; export async function GET(request) { const { searchParams } = new URL(request.url); const imageUrl = searchParams.get('url'); // 建议从服务端会话/环境变量取Token,避免前端暴露 const token = process.env.IMAGE_API_TOKEN || request.headers.get('authorization'); if (!imageUrl) { return new NextResponse('缺少图片地址', { status: 400 }); } try { const response = await fetch(imageUrl, { headers: { Authorization: token, 'Content-Type': 'image/jpeg', }, cache: 'no-store', }); if (!response.ok) { return new NextResponse('获取图片失败', { status: response.status }); } const blob = await response.blob(); return new NextResponse(blob, { headers: { 'Content-Type': 'image/jpeg', }, }); } catch (error) { return new NextResponse('请求异常', { status: 500 }); } }
- 前端组件调用
// SSR组件无需加'use client',客户端组件需要的话自行添加 export default function ProtectedImage() { const targetImageUrl = 'http://example.com/test.jpg'; return ( <img src={`/api/proxy-image?url=${encodeURIComponent(targetImageUrl)}`} alt="受保护图片" /> ); }
方案二:客户端正常发起fetch(需配置CORS)
如果图片服务器允许你的NextJS域名跨域请求,去掉mode: 'no-cors',让fetch能正常携带Authorization头。
修改后的客户端组件代码:
'use client'; import { useState, useEffect } from 'react'; export default function ProtectedImage() { const [blobUrl, setBlobUrl] = useState(null); useEffect(() => { const fetchImage = async () => { const imageUrl = 'http://example.com/test.jpg'; const token = 'Bearer 123456'; // 实际从安全渠道获取,别硬编码 try { const response = await fetch(imageUrl, { headers: { Authorization: token, 'Content-Type': 'image/jpeg', }, cache: 'no-store', }); if (!response.ok) { throw new Error(`请求失败:${response.status}`); } const blob = await response.blob(); const url = URL.createObjectURL(blob); setBlobUrl(url); // 组件卸载时释放Blob资源 return () => URL.revokeObjectURL(url); } catch (error) { console.error('获取图片出错:', error); } }; fetchImage(); }, []); if (!blobUrl) { return <div>图片加载中...</div>; } return <img src={blobUrl} alt="受保护图片" />; }
前提:图片服务器需配置CORS响应头,允许你的域名携带Authorization头:
Access-Control-Allow-Origin: 你的NextJS域名Access-Control-Allow-Headers: Authorization
方案三:配合next/image组件自定义loader
如果使用next/image优化图片加载,可以自定义loader指向代理API:
import Image from 'next/image'; const protectedImageLoader = ({ src }) => { return `/api/proxy-image?url=${encodeURIComponent(src)}`; }; export default function ProtectedImage() { return ( <Image loader={protectedImageLoader} src="http://example.com/test.jpg" alt="受保护图片" width={500} height={500} /> ); }
API路由逻辑同方案一。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

