You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NextJS中展示受Authorization Header保护的图片?

解决NextJS中展示受Authorization Header保护的图片问题

问题根源

浏览器原生<img>标签发起的请求无法自定义Authorization头;而你代码中设置的mode: 'no-cors'会强制浏览器忽略所有自定义请求头(包括Authorization),导致请求始终未授权,返回401错误。

可行解决方案

方案一:用NextJS API路由做代理(推荐,适配SSR场景)

利用服务端请求不受浏览器CORS限制、可正常携带Authorization头的特性,创建一个API路由作为中间层转发图片请求,前端直接请求这个路由即可。

  1. 创建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 });
  }
}
  1. 前端组件调用
// 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:52:32