Python 2.7 上载文件的OneDrive API Python request.post产生401错误

Python 2.7 上载文件的OneDrive API Python request.post产生401错误,python-2.7,azure-active-directory,adal,onedrive,Python 2.7,Azure Active Directory,Adal,Onedrive,我正在尝试使用OneDrive API、ADAL和Python request.post将文件上载到Sharepoint文件夹,但遇到401错误 ADAL授权的作用是获取正确的令牌响应并生成可行的访问\u令牌 我可以使用access\u令牌从同一Sharepoint文件夹下载文件 虽然这仅在我手动将代码创建的打印文件\u urlurl复制到浏览器中时有效。但是urllib.urlretrieve(文件url,本地文件名)只创建一个名为myfilename.csv的文件,其内容403禁止 我的授权

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

ADAL授权的作用是获取正确的令牌响应并生成可行的
访问\u令牌

我可以使用
access\u令牌
从同一Sharepoint文件夹下载文件

虽然这仅在我手动将代码创建的
打印文件\u url
url复制到浏览器中时有效。但是
urllib.urlretrieve(文件url,本地文件名)
只创建一个名为
myfilename.csv
的文件,其内容
403禁止

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

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') 
令牌响应是正确的,使用来自它的访问令牌,以下代码生成一个
文件\u url
url,我可以手动复制并粘贴到成功下载文件的浏览器中。但是
urllib.urlretrieve(文件url,本地文件名)
仅创建名为
myfilename.csv
的文件,其内容
403禁止

## 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 
My Azure广告应用程序具有以下权限:

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看起来可以吗?非常确定我发送的头,文件夹和文件正确

编辑以添加:

鉴于下载代码返回
403禁止
和上传代码返回
401未经授权
这两个事实,我怀疑问题在于
urllib
请求
如何发送URL

编辑以添加:

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

https://mydomain.sharepoint.com/_api/v1.0/files/root
返回以下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_和用户名密码。这将允许您访问图形(您可以在其中访问OneDrive),否则您只能在该令牌中获得登录权限

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

token_response = ada.acquire_token_with_username_password(
    authorization_url,
    username,
    password,
    client_id
    resource_url
)
如果您得到一个错误,告诉您需要client\u secret o client\u断言。您需要注册一个新的Azure应用程序并选择本机客户端。 如果您收到一个错误,说您需要一个交互式提示,您需要在浏览器中首次手动同意该应用程序,方法是导航到

https://login.microsoftonline.com/mydomain.com/oauth2/authorize?client_id=client_id&resource=resource_url&response_type=code+id_token&nonce=1234
确保替换mydomain.com、客户端id和资源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
有关在此处获取文件的详细信息:

至于上传,您还需要将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
有关在此处上载文件的详细信息:

这里有几个问题需要解决

首先,您需要将客户机id和资源传递给您的acquire_token_和用户名密码。这将允许您访问图形(您可以在其中访问OneDrive),否则您只能在该令牌中获得登录权限

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

token_response = ada.acquire_token_with_username_password(
    authorization_url,
    username,
    password,
    client_id
    resource_url
)
如果您得到一个错误,告诉您需要client\u secret o client\u断言。您需要注册一个新的Azure应用程序并选择本机客户端。 如果您收到一个错误,说您需要一个交互式提示,您需要在浏览器中首次手动同意该应用程序,方法是导航到

https://login.microsoftonline.com/mydomain.com/oauth2/authorize?client_id=client_id&resource=resource_url&response_type=code+id_token&nonce=1234
确保替换mydomain.com、客户端id和资源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
有关在此处获取文件的详细信息:

至于上传,您还需要将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
有关在此处上载文件的详细信息:

您确定您的文件下载正确吗?我尝试了你的代码,而不是下载文件,它给了我一个html文件,将我重定向到其他地方。该死的,你是对的,它没有正确下载。它创建了一个名为
myfilename.csv
的文件,但内容仅
403禁止
。当我打印
文件\u url
并将生成的url直接复制到浏览器中时,它确实正确下载了文件。我将更新问题。您确定您的文件下载正确吗?我尝试了你的代码,而不是下载文件,它给了我一个html文件,将我重定向到其他地方。该死的,你是对的,它没有正确下载。它创建了一个名为
myfilename.csv
的文件,但内容仅
403禁止
。当我打印
文件\u url
并将生成的url直接复制到浏览器中时,它确实正确下载了文件。我将更新问题。好的,我现在明白了,我刚刚用Azure广告验证了一个用户,而不是应用程序。但同时将
客户端id
资源
设置为
。我可以授权关闭
登录.microsoft.com
。需要修改具有默认值的