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

Python生成Azure文件共享SAS令牌时签名不匹配问题排查

问题描述

编写了如下Python代码用于生成Azure文件共享中文件的SAS令牌:

def getParcelFilePath(webcountyval):
    filePath = rf"/plan/IN/{webcountyval}%20parcels.dbf"
    file_sas_token = generate_file_sas(
       account_name=os.environ["AZURE_STORAGE_ACCOUNT_NAME"],
       account_key=os.environ["AZURE_STORAGE_ACCOUNT_KEY"],
       share_name="dev",
       file_path=filePath,
       permission=AccountSasPermissions(read=True),
       expiry=datetime.datetime.now() + datetime.timedelta(hours=8),
       start=datetime.datetime.now()
     )

     filePathWithToken = os.environ["AZURE_STORAGE_SHARE_URL"] + filePath + "?" + file_sas_token
     return(filePathWithToken)

生成的URL粘贴到浏览器后,出现签名不匹配错误:

Signature did not match. String to sign used was r 2024-11-11T23:14:30Z 2024-11-12T07:14:30Z /file/crestlinecapitalstorage/dev/plan/IN/elkhart parcels.dbf 2024-11-04

原因分析

  1. 文件路径编码错误:generate_file_sas函数要求传入文件在存储中的原始未编码路径(即空格就是空格,而非%20)。但代码中直接将URL编码后的%20传入file_path参数,导致Azure计算签名时使用的路径是/plan/IN/elkhart%20parcels.dbf,而实际验证时系统会自动解码为带空格的路径/plan/IN/elkhart parcels.dbf,两者不一致导致签名验证失败。

  2. 时间时区潜在问题:使用datetime.datetime.now()获取本地时间(中部时区),手动加8小时转换为UTC的方式依赖本地系统时区设置,容易出现偏差。Azure SAS要求使用UTC时间,直接调用utcnow()更可靠。

修复方案

修改代码关键点:

  • 传给generate_file_sas的file_path使用原始带空格的路径,不要提前URL编码
  • 时间部分改用datetime.datetime.utcnow()获取UTC时间
  • 拼接最终URL时,再对文件路径进行URL编码

修改后的代码:

import urllib.parse
import datetime
from azure.storage.fileshare import generate_file_sas, AccountSasPermissions
import os

def getParcelFilePath(webcountyval):
    # 使用存储中的原始路径(带空格,不编码)
    filePath = rf"/plan/IN/{webcountyval} parcels.dbf"
    file_sas_token = generate_file_sas(
       account_name=os.environ["AZURE_STORAGE_ACCOUNT_NAME"],
       account_key=os.environ["AZURE_STORAGE_ACCOUNT_KEY"],
       share_name="dev",
       file_path=filePath,
       permission=AccountSasPermissions(read=True),
       # 使用UTC时间,避免本地时区干扰
       expiry=datetime.datetime.utcnow() + datetime.timedelta(hours=8),
       start=datetime.datetime.utcnow()
     )

     # 拼接URL时对路径进行URL编码,去掉开头斜杠避免重复
     encoded_file_path = urllib.parse.quote(filePath.lstrip('/'))
     filePathWithToken = f"{os.environ['AZURE_STORAGE_SHARE_URL']}/{encoded_file_path}?{file_sas_token}"
     return filePathWithToken

验证说明:

修改后,生成SAS时使用的路径和Azure验证时的路径一致(均为带空格的原始路径),签名计算会匹配;同时UTC时间的使用避免了时区导致的时间偏差,进一步保证认证通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 09:42:06