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

使用Graph API的SharePoint Access Token读取文件失败,求解决

解决AudienceUriValidationFailedException错误的方案

错误原因

你遇到的Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException,本质是Access Token的受众(Audience)不匹配:

  • 当前获取的Token是针对Microsoft Graph API的(受众为https://graph.microsoft.com)
  • 但你用这个Token直接请求SharePoint站点的webUrl(比如https://xxx.sharepoint.com/...),SharePoint的受众是自身站点域名,因此会拒绝该Token。

解决方案

有两种可行的解决思路:

思路1:改用Microsoft Graph API读取文件内容(推荐)

直接通过Graph API的文件内容端点获取,Token受众完全匹配,无需访问SharePoint原生URL。

修改代码中读取文件的部分:

# 替换原来的requests.get(list["webUrl"], ...)代码
# 从Graph返回的文件对象中提取关键信息,构造内容请求URL
file_id = item["id"]
# 基于driveId和itemId构造Graph文件内容端点
content_url = f"https://graph.microsoft.com/v1.0/drives/{item['parentReference']['driveId']}/items/{file_id}/content"
# 发起请求时要在Authorization头中加上Bearer前缀
response = requests.get(content_url, headers={"Authorization": f"Bearer {token_result['access_token']}"})

# 验证请求结果
if response.status_code == 200:
    # 保存文件或处理内容
    with open(item["name"], "wb") as f:
        f.write(response.content)
    print(f"成功读取文件:{item['name']}")
else:
    print(f"读取失败,状态码:{response.status_code},错误信息:{response.text}")

思路2:获取针对SharePoint站点的Access Token

如果必须直接访问SharePoint原生REST API,需要重新获取受众为SharePoint站点的Token:

  • 将scope修改为"https://{你的SharePoint站点域名}/.default"(例如https://contoso.sharepoint.com/.default)
  • 调用acquire_token_for_client获取新Token后,用该Token请求SharePoint REST API的文件内容端点(格式为{webUrl}/$value,而非直接请求webUrl)

代码优化建议

你的代码还有几处需要调整的细节:

  • try-except块捕获异常后,需重新发起Graph请求,否则后续会使用失败的响应数据
  • response = requests.get(...)部分缩进错误,需放入if ele.lower() in list["name"].lower()的代码块内
  • Authorization头必须包含Bearer 前缀,格式应为Bearer {access_token}

调整后的核心循环示例:

while True:
    try:
        # 构造正确的Authorization头
        headers = {"Authorization": f"Bearer {token_result['access_token']}"}
        graph_result = requests.get(url=url, headers=headers)
        graph_result.raise_for_status()
    except Exception as e:
        print(f"Graph API请求失败:{str(e)}")
        token_result = client.acquire_token_for_client(scopes=scope)
        # 重新发起请求
        headers = {"Authorization": f"Bearer {token_result['access_token']}"}
        graph_result = requests.get(url=url, headers=headers)
        graph_result.raise_for_status()

    if 'value' in graph_result.json():
        items = graph_result.json()['value']
        for item in items:
            for ele in finalReportNames:
                if ele.lower() in item["name"].lower():
                    clientreportcount += 1
                    # 改用Graph API读取文件内容
                    file_id = item["id"]
                    content_url = f"https://graph.microsoft.com/v1.0/drives/{item['parentReference']['driveId']}/items/{file_id}/content"
                    content_response = requests.get(content_url, headers=headers)
                    if content_response.ok:
                        print(f"成功读取文件:{item['name']}")
                        # 这里可以添加文件内容处理逻辑
                    else:
                        print(f"文件读取失败:{content_response.text}")
        # 处理分页
        if '@odata.nextLink' in graph_result.json():
            url = graph_result.json()['@odata.nextLink']
            graphlinkcount += 1
        else:
            break

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:14:54