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
我怀疑问题出在 urllib
和 requests
正在发送 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
我正在尝试使用 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
我怀疑问题出在 urllib
和 requests
正在发送 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