使用 Python 从个人 OneDrive 下载文件
问题描述
我有一个 Python 脚本,它在 AWS EC2 Ubuntu 机器上定期运行.
I have a Python script that is running periodically on an AWS EC2 Ubuntu machine.
此脚本从某些文件中读取数据,有时还会更改其中的数据.
This script reads data from some files and sometimes changes data in them.
我想从 OneDrive 下载这些文件,用它们做我自己的事情,然后将它们上传回 OneDrive.
I want to download these files from OneDrive, do my own thing with them, and upload them back to OneDrive.
我希望自动完成此操作,无需用户批准任何登录名或凭据.我可以这样做一次(即在第一次运行时批准登录),但其余的必须自动运行,无需再次请求批准(当然,除非权限发生变化).
I want this to be done automatically, without the need for a user to approve any login or credentials. I'm ok with doing it once (i.e. approving the login on the first run) but the rest has to run automatically, without asking ever again for approvals (unless the permissions change, of course).
最好的方法是什么?
我一直在阅读有关 Microsoft Graph API 的文档,但我在身份验证部分遇到了困难.我在 Azure AAD 中创建了一个应用程序,提供了示例权限(用于测试)并创建了一个秘密凭据.
I've been reading the documentation on Microsoft Graph API but I'm struggling with the authentication part. I've created an application in Azure AAD, gave the sample permissions (to test) and created a secret credential.
解决方案
我设法做到了.我不确定这是否是最好的方法,但它现在正在工作.它每小时自动运行一次,我不需要触摸它.
I managed to do it. I'm not sure if it's the best way but it is working now. It's running automatically every hour and I don't need to touch it.
我关注了 https://docs.microsoft.com/en-gb/azure/active-directory/develop/v2-oauth2-auth-code-flow
这就是我所做的.
Azure 门户
- 创建一个应用程序.Azure Active Directory -> 应用注册 -> 来自个人帐户的应用程序
- 在支持的帐户类型中,选择具有个人 Microsoft 帐户的帐户类型.
- 在重定向 URI 中,选择公共客户端/本机.我们稍后会添加特定的 URI.
- 在应用程序详细信息的概述部分中,记下应用程序(客户端)ID.我们稍后会用到它.
- 在身份验证部分,点击添加平台并选择桌面+设备.你可以使用你自己的,我选择了一个建议:https://login.microsoftonline.com/common/oauth2/nativeclient
- 在 API 权限 部分中,您必须添加您的应用将使用的所有权限.我添加了 User.Read、Files.ReadWrite 和 offline_access.offline_access 是为了能够获取 刷新令牌,这对于在不要求用户登录的情况下保持应用运行至关重要.
- 我没有创建任何证书或秘密.
- Create an application. Azure Active Directory -> App Registrations -> Applications from personal account
- In Supported account types, choose the one that has personal Microsoft accounts.
- In Redirect URI, choose Public client/native. We'll add the specific URI later.
- In the application details, in the section Overview, take note of the Application (client) ID. We'll need this later.
- In the section Authentication, click Add a Platform and choose Desktop + devices. You can use your own, I chose one of the suggested: https://login.microsoftonline.com/common/oauth2/nativeclient
- In the section API permissions, you have to add all the permissions that your app will use. I added User.Read, Files.ReadWrite and offline_access. The offline_access is to be able to get the refresh token, which will be crucial to keep the app running without asking the user to login.
- I did not create any Certificate or Secret.
网络
看起来我们第一次必须使用浏览器或模拟类似的东西才能获得令牌.
Looks like to get a token for the first time we have to use a browser or emulate something like that.
必须有一种编程方式来做到这一点,但我不知道该怎么做.我也考虑过为此使用 Selenium,但由于这只是一次,而且我的应用程序每小时都会请求令牌(保持令牌新鲜),所以我放弃了这个想法.
There must be a programmatic way to do this, but I had no idea how to do it. I also thought about using Selenium for this, but since it's only one time and my app will request tokens every hour (keeping the tokens fresh), I dropped that idea.
如果我们添加新的权限,我们拥有的令牌将失效,我们必须再次执行此手动部分.
If we add new permissions, the tokens that we have will become invalid and we have to do this manual part again.
- 打开浏览器并转到下面的 URL.使用您在 Azure 门户中设置的 Scopes 和 Redirect URI.
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=your_app_client_id&response_type=code&redirect_uri=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fnativeclient&response_mode=query&scope=User.Read%20offline_access%20Files.ReadWrite
该 URL 会将您重定向到您设置的 重定向 URI,并带有 code=something在网址中.复制那个东西.
That URL will redirect you to the Redirect URI that you set up and with a code=something in the URL. Copy that something.
- 使用 FORM URL Encoded 类型执行 POST 请求.我为此使用了 https://reqbin.com/.
端点:https://login.microsoftonline.com/common/oauth2/v2.0/token
表单网址:grant_type=authorization_code&client_id=your_app_client_id&code=use_the_code_returned_on_previous_step
Form URL: grant_type=authorization_code&client_id=your_app_client_id&code=use_the_code_returned_on_previous_step
这将返回一个访问令牌和一个刷新令牌.将刷新令牌存储在某处.我将它保存在一个文件中.
This will return an Access Token and a Refresh Token. Store the Refresh Token somewhere. I'm saving it in a file.
Python
# Build the POST parameters
params = {
'grant_type': 'refresh_token',
'client_id': your_app_client_id,
'refresh_token': refresh_token_that_you_got_in_the_previous_step
}
response = requests.post('https://login.microsoftonline.com/common/oauth2/v2.0/token', data=params)
access_token = response.json()['access_token']
new_refresh_token = response.json()['refresh_token']
# ^ Save somewhere the new refresh token.
# I just overwrite the file with the new one.
# This new one will be used next time.
header = {'Authorization': 'Bearer ' + access_token}
# Download the file
response = requests.get('https://graph.microsoft.com/v1.0/me/drive/root:' +
PATH_TO_FILE + '/' + FILE_NAME + ':/content', headers=header)
# Save the file in the disk
with open(file_name, 'wb') as file:
file.write(response.content)
所以基本上,我总是更新刷新令牌.
So basically, I have the Refresh Token always updated.
我使用该刷新令牌调用令牌端点,API 为我提供了在当前会话期间使用的访问令牌和新的刷新令牌.
I call the Token endpoint using that Refresh Token, and the API gives me an Access Token to use during the current session and a new Refresh Token.
我下次运行程序时使用这个新的刷新令牌,以此类推.
I use this new Refresh Token the next time I run the program, and so on.
相关文章