2016-05-23 65 views
0

我想使用OneDrive API,ADAL和Python request.post上傳文件到Sharepoint文件夾,但得到401錯誤。OneDrive API Python request.post上傳文件產生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 = '[email protected]' 
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看看好嗎?很確定我正確地發送標題,文件夾和文件。

編輯補充:

給定的事實,無論下載的代碼返回403 Forbidden和上傳的代碼返回401 Unauthorized我懷疑問題是與如何urllibrequests要發送的網址。

編輯補充:

試圖建立文件的URL中GET並投入使用。我在身份驗證後,我可以手動輸入這個網址到瀏覽器:

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\/'."} 

我認爲得到這個具體參考的文件是什麼,我需要,使其工作。

+1

是你一定要正確下載你的文件?我試過你的代碼,而不是下載文件,它給了我一個HTML文件,將我重定向到別的地方。 –

+0

該死的你是對的,它沒有正確下載。它創建一個名爲'myfilename.csv'的文件,但內容只是'403 Forbidden'。當我打印'file_url'並直接將結果url複製到瀏覽器中時,它會正確下載文件。我會更新問題。 – curtisp

回答

1

有幾件事情需要修復。

首先,您需要將客戶端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」的方法,但我認爲這不起作用(當我測試它時沒有工作)。你需要一個不同的網址,併發送不記名的令牌,就像你在發送請求時一樣。 https://dev.onedrive.com/items/download.htm

至於上傳,你需要改變你的網址爲好,相同的值作爲GET情況下,也從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 

更多信息放。在這裏上傳文件

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

+0

好吧,我現在明白了,我剛剛使用Azure AD驗證用戶而不是應用程序。但[[adal.acquire_token_with_username_password'](https://github.com/AzureAD/azure-activedirectory-library-for-python/blob/master/adal/__init__.py)將'client_id'和'resource'設置爲' None'。 – curtisp

+0

我能夠授權'login.microsoftonline.com'。需要修改[__init __。py'文件中的ADAL'class _DefaultValues'](https://github.com/AzureAD/azure-activedirectory-library-for-python/blob/master/adal/__init__.py) 'client_id'和'resource'的默認值使它們與我的應用匹配,例如'client_id' =我的Azure AD應用的client_id和'resource' ='https://tenant.sharepoint.com/'to解決無效的受衆問題。還將file_url修改爲'https://tenant.sharepoint.com/_api/v2.0/drive/root:/myfoldername/myfilename.csv:/content'。 – curtisp