OneDrive API Python request.post 上传文件产生401错误

OneDrive API Python request.post to upload file produces 401 error

我正在尝试使用 OneDrive API、ADAL 和 Python request.post 将文件上传到 Sharepoint 文件夹,但出现 401 错误。

ADAL 授权正在获取正确的令牌响应并生成可行的 access_token

我可以使用 access_token 从同一个 Sharepoint 文件夹下载文件。

虽然这只有在我手动将代码创建的 print file_url url 复制到浏览器中时才有效。但是 urllib.urlretrieve(file_url, local_file_name) 只创建一个名为 myfilename.csv 的文件,内容为 403 Forbidden.

我的授权使用硬编码的用户名和密码,我以明文形式保存刷新令牌,并且总是在检索令牌响应时检索它:

import adal
import urllib
import requests

## set variables
username = 'username@mydomain.onmicrosoft.com'
password = 'mypassword'
authorization_url = 'https://login.windows.net/mydomain.onmicrosoft.com' # Authority
redirect_uri = 'https://login.microsoftonline.com/login.srf'
client_id = 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx' # Client id

## use ADAL to create token response
token_response = adal.acquire_token_with_username_password(
        authorization_url,
        username,
        password
    )

## create refresh token and save it to use later 
refresh_token = token_response['refreshToken']
refresh_token_file = open('refresh_token.txt', 'w')
refresh_token_file.write(refresh_token)
refresh_token_file.close()

## get saved refresh token and use it to get new token response
refresh_token = open('refresh_token.txt', 'r').read()
token_response = adal.acquire_token_with_refresh_token(authorization_url, str(refresh_token))

## get access_token from token response
access_token = token_response.get('accessToken') 

令牌响应是正确的,使用它的访问令牌,以下代码生成一个 file_url url,我可以手动将其复制并粘贴到浏览器中,从而成功下载文件。但是 urllib.urlretrieve(file_url, local_file_name) 只创建一个名为 myfilename.csv 的文件,其内容为 403 Forbidden:

## download file
file_url = 'https://mydomain.sharepoint.com/Shared%20Documents/myfoldername/myfilename.csv?token_response=' + str(access_token)
local_file_name = 'myfilename.csv'
urllib.urlretrieve(file_url, local_file_name)

但是我还没有能够成功上传到这个 Sharepoint 文件夹。目前我有以下内容:

# upload file
site_url = 'https://mydomain.sharepoint.com/'
headers = {'Authorization':'BEARER ' + str(access_token)}
r = requests.post(site_url, files={'Shared%20Documents/myfoldername/myfilename.csv': open('myfilename.csv', 'rb')}, headers=headers)

print r.text

产生响应

401 UNAUTHORIZED 

我的 Azure AD 应用有权限:

Read and write all user files 
Read and write items and lists in all site collections
(not sure both are needed to upload files)

我的 request.post 看起来还好吗?很确定我正在正确发送 header、文件夹和文件。

编辑添加:

考虑到下载代码 returns 403 Forbidden 和上传代码 returns 401 Unauthorized 我怀疑问题出在 urllibrequests 正在发送 url。

编辑添加:

正在尝试构建文件 url 以在 GET 和 PUT 中使用。通过身份验证后,我可以在浏览器中手动输入此 url:

https://mydomain.sharepoint.com/_api/v1.0/files/root

returns 跟随 XML:

{"@odata.context":"https://mydomain.sharepoint.com/_api/v1.0/$metadata#files/$entity"
,"@odata.type":"#Microsoft.FileServices.Folder"
,"@odata.id":"https://mydomain.sharepoint.com/_api/v1.0/files/01QEW7725BZO3N6Y2GOV54373IPWSELRRZ"
,"@odata.editLink":"files/01QEW7725BZO3N6Y2GOV54373IPWSELRRZ"
,"createdBy":null
,"eTag":null
,"id":"01QEW7725BZO3N6Y2GOV54373IPWSELRRZ"
,"lastModifiedBy":null
,"name":"/"
,"parentReference":null
,"size":0
,"dateTimeCreated":"2013-07-31T02:35:57Z"
,"dateTimeLastModified":"2016-05-23T03:55:46Z"
,"type":"Folder"
,"webUrl":"https://mydomain.sharepoint.com/Shared%20Documents"
,"childCount":1}

但是还没有找到引用该文件的正确语法。例如,这不起作用:

https://mydomain.sharepoint.com/_api/v1.0/files/root:/myfoldername/myfilename.csv:/content

这是返回错误:

    {"error":"invalid_client","error_description":"Invalid audience Uri 'https:\/\/m
anagement.core.windows.net\/'."}

我认为获得对文件的特定引用是我需要的才能使其正常工作。

这里有几个问题需要解决。

首先,您需要将客户端 ID 和资源传递给您的 acquire_token_with_username_password。这将允许您访问 Graph(您可以在其中访问 OneDrive),否则您只是在该令牌中获得登录权限。

resource_url = "https://graph.microsoft.com";

token_response = ada.acquire_token_with_username_password(
    authorization_url,
    username,
    password,
    client_id
    resource_url
)

如果您收到一条错误消息,提示您 client_secret o client_assertion 是必需的。您需要注册一个新的 Azure 应用程序并选择 Native Client。 如果您收到一条错误提示您需要交互式提示,您需要在浏览器中首次通过导航至

手动同意该应用
https://login.microsoftonline.com/mydomain.com/oauth2/authorize?client_id=client_id&resource=resource_url&response_type=code+id_token&nonce=1234

确保替换 mydomain.com、client_id 和 resource_url。

您第一次只需执行一次。使用浏览器登录并同意后,您应该不会再收到该交互提示错误。

要下载文件,不确定您是从哪里获得“?token_response=x”方法的,但我认为这行不通(我测试时行不通)。您需要一个不同的 url 并发送不记名令牌,就像您在 post 请求中所做的那样。

site_url = 'https://graph.microsoft.com/v1.0/drive/root:/myfoldername/myfilename.csv:/content'
headers = {'Authorization':'BEARER ' + str(access_token)}
r = requests.get(site_url, headers=headers)
print r.text

有关在此处获取文件的更多信息: https://dev.onedrive.com/items/download.htm

至于上传,您还需要将 URL 更改为与 GET 大小写相同的值,并将 POST 更改为 PUT。

site_url = 'https://graph.microsoft.com/v1.0/drive/root:/myfoldername/myfilename.csv:/content'
headers = {'Authorization':'BEARER ' + str(access_token)}
r = requests.put(site_url, data = open('myfilename.csv', 'rb')}, headers=headers)
print r.text

有关在此处上传文件的更多信息: https://dev.onedrive.com/items/upload_put.htm