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

使用Python通过Graph API读取SharePoint列表及获取AccessToken求助

解决Microsoft Graph API获取AccessToken及读取SharePoint列表行问题

问题背景

  • 目标:通过Python调用Microsoft Graph API读取SharePoint列表数据
  • 现状:已能获取SharePoint列表的ID和名称,但无法读取列表行数据
  • 限制:账号开启MFA,无管理员权限无法获取Client Secret,仅能通过手机验证码登录
  • 错误:使用ADAL设备码流获取AccessToken时,触发AdalError: Unexpected polling state invalid_client

现有获取列表代码

from pypac import PACSession
session = PACSession()
headers = {
    'authorization': f'Bearer {access_token}',
}

response = session.request("GET",
    'https://graph.microsoft.com/v1.0/sites/xxx.sharepoint.com:/sites/xxx/xxx/BTADMCA:/lists?select=id,name',
    headers=headers,
)
response.json()

原AccessToken获取代码(报错)

import adal

authority_url = "https://login.microsoftonline.com/common"
client_id = "de8bc8b5-d9f9-48b1-a8ad-b748da725064"

auth_context = adal.AuthenticationContext(authority_url)

# Initiate device code flow
device_code = auth_context.acquire_user_code("https://graph.microsoft.com/", client_id)
print(device_code['message'])

# Poll for token using device code
token_response = auth_context.acquire_token_with_device_code("https://graph.microsoft.com/", device_code, client_id)

access_token = token_response["accessToken"]
print("Access token acquired successfully:", access_token)

错误信息

AdalError                                 Traceback (most recent call last)
<ipython-input-24-afa3aa1fa6be> in <module>
     11 
     12 # Poll for token using device code
---> 13 token_response = auth_context.acquire_token_with_device_code("https://graph.microsoft.com/", device_code, client_id)
     14 
     15 access_token = token_response["accessToken"]

c:\ProgramData\python36\lib\site-packages\adal\authentication_context.py in acquire_token_with_device_code(self, resource, user_code_info, client_id)
    309             return token
    310 
---> 311         return self._acquire_token(token_func, user_code_info.get('correlation_id', None))
    312 
    313     def cancel_request_to_get_token_with_device_code(self, user_code_info):

c:\ProgramData\python36\lib\site-packages\adal\authentication_context.py in _acquire_token(self, token_func, correlation_id)
    126             correlation_id or self.correlation_id, self._call_context.get('enable_pii', False))
    127         self.authority.validate(self._call_context)
---> 128         return token_func(self)
    129 
    130     def acquire_token(self, resource, user_id, client_id):

c:\ProgramData\python36\lib\site-packages\adal\authentication_context.py in token_func(self)
    302                 self._token_requests_with_user_code[key] = token_request
...
---> 362                                 wire_response)
    363             else:
    364                 try:

AdalError: Unexpected polling state invalid_client

解决方案

一、修复AccessToken获取问题

invalid_client错误的核心原因是ADAL已被微软弃用,对设备码流的支持存在兼容性问题,建议改用MSAL(Microsoft Authentication Library)实现登录。

改用MSAL实现设备码流登录

import msal

# 配置参数
CLIENT_ID = "de8bc8b5-d9f9-48b1-a8ad-b748da725064"  # 保持原客户端ID
AUTHORITY = "https://login.microsoftonline.com/common"
SCOPE = ["https://graph.microsoft.com/Sites.Read.All"]  # 按需调整权限,只读用Sites.Read.All

# 初始化MSAL公共客户端应用
app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)

# 启动设备码流
flow = app.initiate_device_flow(scopes=SCOPE)
if "user_code" not in flow:
    raise ValueError(f"设备码流初始化失败: {flow.get('error_description')}")

# 输出用户操作指引
print(flow["message"])

# 轮询获取令牌
result = app.acquire_token_by_device_flow(flow)
if "access_token" in result:
    access_token = result["access_token"]
    print("Access Token获取成功")
else:
    raise Exception(f"获取令牌失败: {result.get('error')}, {result.get('error_description')}")

关键说明

  • 权限范围SCOPE需匹配实际需求,若需要写入权限可改为Sites.ReadWrite.All
  • 无管理员权限时,用户登录后会自动完成授权(需租户允许用户自行授权第三方应用)

二、读取SharePoint列表行数据

获取有效AccessToken后,使用以下代码读取列表行:

from pypac import PACSession

session = PACSession()
headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/json'
}

# 替换为你的站点路径和目标列表ID
site_url = "xxx.sharepoint.com:/sites/xxx/xxx/BTADMCA:"
list_id = "你的列表ID"  # 从之前获取列表的接口返回中提取

# 请求列表行数据,可通过select指定需要的字段
response = session.get(
    f'https://graph.microsoft.com/v1.0/sites/{site_url}/lists/{list_id}/items?select=id,fields',
    headers=headers
)

if response.status_code == 200:
    items = response.json()
    print("列表行数据:", items)
else:
    print(f"请求失败,状态码: {response.status_code}, 错误信息: {response.json()}")

注意事项

  • 列表ID必须是Graph API返回的标准ID,而非SharePoint界面显示的名称
  • 若列表行数超过100条,需处理分页:通过$top参数调整单次返回数量,或遍历响应中的@odata.nextLink链接获取后续数据
  • 可通过select=fields/字段名1,fields/字段名2精准指定需要返回的字段,减少数据传输量

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:30:54