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

使用Python调用SharePoint Rest API遇403权限错误的解决咨询

问题

我尝试通过Python的office365库访问SharePoint文件夹并获取文件,代码如下:

# Import libraries
from office365.sharepoint.client_context import ClientContext
from office365.runtime.auth.client_credential import ClientCredential

# Config for Sharepoint (to be stored in env later)
SP_CLIENT_ID = xxx
SP_CLIENT_SECRET = xxx
SP_URL = 'https://<organization_url>.sharepoint.com/sites/<site-name>'
relative_folder_url = '/Shared%20Documents/<subfolder>'

# App-based authentication with access credentials
context = ClientContext(SP_URL).with_credentials(ClientCredential(SP_CLIENT_ID, SP_CLIENT_SECRET))
folder = context.web.get_folder_by_server_relative_url(relative_folder_url)
context.load(folder)
context.execute_query()

# Processes each Sharepoint file in folder
for file in folder.files:
    print(f'Processing file: {file.properties["Name"]}')

运行时抛出403权限错误:

office365.runtime.client_request_exception.ClientRequestException: ('-2147024891, System.UnauthorizedAccessException', 'Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))', "403 Client Error: Forbidden for url: https://<tenant-name>.sharepoint.com/sites/<site-id>/_api/Web/getFileByServerRelativePath(DecodedUrl='%2Fsites%2F<site-name>%2FDocuments%2FGeneral%2F<subfolder>')")

该错误来自context.execute_query()。

我用相同的SP_CLIENT_ID和SP_CLIENT_SECRET在Postman中通过Graph API可以正常获取文件:先生成令牌,再在GET请求中传入令牌即可,说明应用本身的认证没问题。

现在需要解决这个403问题,让Python代码能通过SharePoint REST API查看并下载文件;同时纠结是继续用office365库,还是改用requests这类纯API方式。

解决方案

一、修复office365库的权限问题

核心问题是Azure应用未被授予SharePoint REST API的权限(该权限与Graph API权限相互独立),需按以下步骤配置:

  1. 登录Azure门户,找到对应的应用注册
  2. 进入「API权限」页面,点击「添加权限」
  3. 选择「SharePoint」->「应用权限」
  4. 添加所需权限:
    • 仅查看文件选Sites.Read.All,需下载/修改选Sites.ReadWrite.All
    • 若仅需访问特定站点,可添加Sites.Selected(需额外绑定站点权限)
  5. 点击「授予管理员同意」(需全局管理员操作)

同时修正代码中的路径格式:relative_folder_url无需URL编码,直接使用原始路径即可,库会自动处理编码,修改后代码片段:

relative_folder_url = '/Shared Documents/<subfolder>'

二、改用requests调用Graph API实现文件操作

既然Postman中Graph API已验证可用,直接用requests调用是更快捷的方案,步骤如下:

1. 获取访问令牌

import requests

# 配置参数
tenant_id = "<your-tenant-id>"
client_id = "<your-client-id>"
client_secret = "<your-client-secret>"
site_name = "<your-site-name>"
folder_path = "/Shared Documents/<subfolder>"

# 获取令牌
token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
token_payload = {
    "grant_type": "client_credentials",
    "client_id": client_id,
    "client_secret": client_secret,
    "scope": "https://graph.microsoft.com/.default"
}
token_response = requests.post(token_url, data=token_payload)
access_token = token_response.json()["access_token"]

2. 获取文件夹中的文件列表

# 获取站点ID
site_response = requests.get(
    f"https://graph.microsoft.com/v1.0/sites/{tenant_id}:/sites/{site_name}",
    headers={"Authorization": f"Bearer {access_token}"}
)
site_id = site_response.json()["id"]

# 获取文件夹下的文件
folder_response = requests.get(
    f"https://graph.microsoft.com/v1.0/sites/{site_id}/drive/root:/{folder_path}:/children",
    headers={"Authorization": f"Bearer {access_token}"}
)
files = folder_response.json()["value"]

for file in files:
    print(f"Processing file: {file['name']}")

3. 下载文件

# 下载单个文件示例
file_id = "<file-id-from-previous-step>"
download_response = requests.get(
    f"https://graph.microsoft.com/v1.0/sites/{site_id}/drive/items/{file_id}/content",
    headers={"Authorization": f"Bearer {access_token}"},
    stream=True
)

with open(file["name"], "wb") as f:
    for chunk in download_response.iter_content(chunk_size=8192):
        f.write(chunk)

方案选择建议

  • 若需复杂SharePoint操作(如文档库管理、版本控制等),建议修复office365库的权限问题,该库封装了更多SharePoint特有功能
  • 若仅需文件列表获取和下载,用requests调用Graph API更轻量,且认证流程已验证可用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:07:26