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

使用Ingress Nginx代理Azure Blob Storage时签名不匹配问题

问题原因分析

Azure Blob Storage的共享密钥签名是基于请求主机名、资源路径、请求时间、x-ms-*系列头等核心信息生成的,签名验证时会严格匹配这些信息。你的场景中签名不匹配的核心原因有两点:

  1. 主机名不匹配:应用代码用Ingress域名my.ingress.com生成签名,但Ingress通过upstream-vhost将请求主机头替换为Blob的真实域名teststorage8297.blob.core.windows.net,导致签名计算用的主机名和Blob验证时的主机名不一致。
  2. 路径不匹配:Ingress通过rewrite-target将/blobstorage(.*)重写为$1,SDK生成签名时用的是原始路径/blobstorage/...,但实际转发到Blob的路径是去掉前缀后的/...,路径信息不匹配导致签名失效。

而SAS Token能生效是因为其签名是预先基于Blob真实域名和路径生成的,Ingress仅做转发,不会修改SAS包含的验证要素,因此可以通过验证。

解决方法

方法一:修改应用代码,确保签名要素与Blob验证一致

调整SDK的请求逻辑,让签名计算使用Blob真实域名,同时请求发送到Ingress地址:

this.aborterController = new AbortController(); 
const storageName = getFileStorageBlobDbConfigs().storageName;
const sharedKeyCredential = new AzureStorage.StorageSharedKeyCredential(  
  storageName,     
  getFileStorageBlobDbConfigs().key1,     
);

// 自定义Pipeline,拦截请求修改URL但保留签名用的主机头
const pipeline = AzureStorage.newPipeline(sharedKeyCredential);
pipeline.filters.push({
  async policy(next) {
    return async (request) => {
      // 保存Blob真实主机名,用于签名计算
      const originalHost = request.url.host;
      // 将请求URL替换为Ingress地址,保留原始路径的资源部分
      const ingressPath = `/blobstorage/${request.url.pathname.substring(1)}`;
      request.url = new URL(`https://my.ingress.com${ingressPath}`);
      // 强制设置Host头为Blob真实域名,确保验证时匹配
      request.headers.set('Host', originalHost);
      return next(request);
    };
  }
});

// 用Blob真实域名初始化Client,配合自定义Pipeline转发到Ingress
this.blobServiceClient = new AzureStorage.BlobServiceClient(        
  `https://${storageName}.blob.core.windows.net`,
  pipeline,
);

// 连接校验
try {
  await new AzureBlobStorage().checkConnection();
} catch (error) {
  Logger.error(`连接Azure Blob Storage失败!原因是: ${(error as { message: string }).message}`);
}

方法二:调整Ingress配置,适配签名规则(局限性较大)

若不想修改代码,可调整Ingress配置避免路径重写和主机头冲突,但需注意会占用整个Ingress域名:

  1. 移除rewrite-target、use-regex注解
  2. 将Ingress路径改为/,直接映射到Blob根路径
  3. 保留upstream-vhost确保Blob能识别存储账户

修改后的Ingress配置片段:

metadata:
  annotations:
    # 移除rewrite-target和use-regex
    cert-manager.io/cluster-issuer: letsencrypt-production
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/upstream-vhost: teststorage8297.blob.core.windows.net
spec:
  rules:
  - host: my.ingress.com
    http:
      paths:
      - backend:
          service:
            name: proxy-to-blob-storage
            port:
              number: 443
        path: /
        pathType: Prefix

方法三:使用Istio VirtualService优化转发(集群已部署Istio)

利用Istio的请求重写和头管理能力,更灵活地适配签名规则:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: blob-storage-vs
  namespace: default
spec:
  hosts:
  - my.ingress.com
  gateways:
  - istio-ingressgateway
  http:
  - match:
    - uri:
        prefix: /blobstorage/
    rewrite:
      uri: /
    route:
    - destination:
        host: teststorage8297.blob.core.windows.net
        port:
          number: 443
    headers:
      request:
        set:
          Host: teststorage8297.blob.core.windows.net

同时修改应用代码,让SDK生成的路径为Blob根路径(即去掉/blobstorage前缀),确保签名路径和转发后的路径一致。

内容的提问来源于stack exchange,提问作者user26640084

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:47:07