使用Python从SharePoint获取文件遇AADSTS53003错误求解决
问题描述
我用Python代码从SharePoint拉取文件时触发错误,具体报错:
An error occurred while retrieving token from XML response: AADSTS53003: Access has been blocked by Conditional Access policies. The access policy does not allow token issuance
原代码如下:
import os import shutil from office365.runtime.auth.authentication_context import AuthenticationContext from office365.sharepoint.client_context import ClientContext sharepoint_url = "Sharepoint_site_url" site_url = "site url" username = "My_username" password = "Password" # File path components library_name = "Shared Documents" folder_name = "ABCD" # Construct the full file path file_path = f"https://xyz.sharepoint.com/sites/site_name/{library_name}/{folder_name}/" # Encode the file path encoded_file_path = file_path.replace(" ", "%20") # Replace spaces with %20 print(encoded_file_path) # Authenticate with SharePoint ctx_auth = AuthenticationContext(sharepoint_url) if ctx_auth.acquire_token_for_user(username, password): # Connect to SharePoint site ctx = ClientContext(site_url, ctx_auth) web = ctx.web ctx.load(web) # Get all files in the SharePoint folder files = ctx.web.get_folder_by_server_relative_path(file_path).files ctx.load(files) ctx.execute_query() # Create a folder on the C drive c_drive_folder1 = "C:/ENTERP/Raw" c_drive_folder2 = "C:/ENTERPR/Processed" os.makedirs(c_drive_folder1, exist_ok=True) os.makedirs(c_drive_folder2, exist_ok=True) # Download and save each file to the C drive folder for file in files: print(1) file_name = file.properties["Name"] file_url = f"{site_url}/{library_name}/{folder_name}/{file_name}" file_content = ctx.web.get_file_by_server_relative_path(file_url).read().execute_query() # Save the file to the C drive folder file_path_on_c_drive = os.path.join(c_drive_folder1, file_name) with open(file_path_on_c_drive, "wb") as local_file: local_file.write(file_content) print(f"Downloaded and saved: {file_name} to {file_path_on_c_drive}") print("Download process completed.") else: print("Failed to authenticate with SharePoint.")
一、错误根源与直接解决步骤
这个错误是Azure AD条件访问策略拦截了令牌发放,和代码本身无关,需先处理权限问题:
- 联系公司IT管理员,让他们检查:
- 你的账号是否允许从当前设备/网络访问SharePoint(比如是否要求合规设备、指定IP段)
- 账号是否启用了MFA(多因素认证),如果是,单纯的用户名密码认证会被策略禁止
- 企业策略是否允许使用"用户名密码流"这种认证方式(多数企业会禁用这种不安全的方式)
- 若启用了MFA,必须改用支持MFA的认证方式,比如设备代码流或交互式认证
二、替代认证方案
方案1:设备代码流(适合手动触发的脚本,支持MFA)
修改认证逻辑,通过浏览器输入验证码完成认证,绕过用户名密码限制:
import os from office365.sharepoint.client_context import ClientContext from office365.runtime.auth.device_code_provider import DeviceCodeProvider # 替换成你的站点URL和Azure AD应用ID(需IT管理员创建授权) sharepoint_site_url = "https://xyz.sharepoint.com/sites/site_name" client_id = "你的Azure AD应用客户端ID" # 初始化设备代码认证 auth_provider = DeviceCodeProvider(sharepoint_site_url, client_id) ctx = ClientContext(sharepoint_site_url, auth_provider) # 触发认证流程:控制台会显示链接和验证码,打开链接输入验证码后用账号登录(支持MFA) web = ctx.web ctx.load(web) ctx.execute_query() print(f"已成功连接到站点: {web.properties['Title']}") # 文件夹配置 library_name = "Shared Documents" folder_name = "ABCD" local_save_path = "C:/ENTERP/Raw" os.makedirs(local_save_path, exist_ok=True) # 获取目标文件夹下的所有文件 server_relative_folder_path = f"/sites/site_name/{library_name}/{folder_name}" folder = ctx.web.get_folder_by_server_relative_path(server_relative_folder_path) files = folder.files ctx.load(files) ctx.execute_query() # 下载每个文件 for file in files: file_name = file.properties["Name"] # 直接读取文件内容 file_content = file.read().execute_query() # 保存到本地 local_file_path = os.path.join(local_save_path, file_name) with open(local_file_path, "wb") as f: f.write(file_content) print(f"已下载文件: {file_name} 到 {local_file_path}") print("所有文件下载完成")
注意:需要IT管理员在Azure AD中注册应用,授予Sites.Read.All权限后提供client_id。
方案2:证书认证(适合无人值守的自动化脚本)
如果脚本需要定时自动运行,可使用证书认证,无需人工交互:
import os from office365.sharepoint.client_context import ClientContext from office365.runtime.auth.client_credential import ClientCredential sharepoint_site_url = "https://xyz.sharepoint.com/sites/site_name" client_id = "Azure AD应用客户端ID" cert_path = "你的证书文件路径.pfx" cert_password = "证书密码" # 用证书初始化认证 auth_cred = ClientCredential(client_id, cert_path, cert_password) ctx = ClientContext(sharepoint_site_url, auth_cred) # 验证连接 web = ctx.web ctx.load(web) ctx.execute_query() print(f"已连接到站点: {web.properties['Title']}") # 后续文件下载逻辑和方案1一致
说明:需IT管理员创建带证书的Azure AD应用,并授予相应SharePoint权限。
三、原代码的其他问题修正
- 缩进错误:原代码中
for file in files:的缩进不正确,应放在if ctx_auth.acquire_token_for_user(...)的代码块内,否则会触发变量未定义错误 - 路径错误:
get_folder_by_server_relative_path需要传入服务器相对路径(如/sites/site_name/Shared Documents/ABCD),而非完整URL
内容的提问来源于stack exchange,提问作者Akshay Kumar
相关产品推荐
相关产品推荐

