的认证是通过 OAuth 2.0 协议的,这是一项开放的认证协议,第三方应用程序和网站可以对认证用户保护的资源进行有限的访问而不需要传输密码信息。基本的 OAuth 2.0 访问场景包含4步,
- 首先,您需要取得用于认证的数据 (客户的 ID 和密码),这些数据是由网站生成的,并且网站和应用程序都是知道的。
- 在应用程序能够访问个人数据之前,它应当收到访问令牌,一个这样的令牌可以提供由'scope'变量定义的不同级别的访问。当请求访问令牌时,应用程序可以在'scope'参数中发送一个或多个值,为了创建这个请求,应用程序可以使用系统浏览器和 web service 请求。有些请求需要在用户登录他们账户的时候有一个认证步骤,在登录之后,用户被询问,他们是否准备给应用程序请求以许可,这个过程被称为用户同意(user consent)。如果用户提出同意,认证服务器就给应用程序提供认证编码,使得应用程序可以获得访问令牌,如果用户没有同意,服务器就返回错误。
- 在应用程序收到访问令牌之后,它会以HTTP认证头的形式发送它,访问点只有在请求的'scope'参数中有描述的操作和资源时才是有效的,例如,如果许可了 Google Drive的访问令牌,它不会提供对 Google contacts(谷歌联系人)的访问,但是,应用程序可以对Google Drive多次发送访问令牌以进行允许的操作。
- 令牌的生命周期是有限的,如果应用程序在访问令牌过期后还需要访问,它可以取得一个更新令牌来允许应用程序取得新的访问令牌。
2. 准备访问 Google Drive
为应用程序创建一个新的项目。转到项目面板 ("选择一个项目"按钮或者 Ctrl + O). 创建一个新的项目 (+).
在新打开的页面,设置项目名称,同意使用声明并确认创建。
从面板中选择新项目并把它与Google Drive API关联,为此, 在管理器 API 开发库中选择 Drive API,并且在新的页面点击Enable(启用)来激活它。
新的页面提示我们创建信任以使用 API. 点击 "Create credentials(创建信任)" 来这样做。
Google 控制台提供了向导来选择认证类型,但是我们不需要它。点击 "client ID". 下一步,Google 再次警告我们需要配置访问确认页面,点击 "Configure consent screen(配置同意屏幕)" 来这样做。
在新打开的页面中,只填充 "Product name shown to users(向用户显示的产品名称)",其它栏位都保持默认值。下一步,把应用程序类型设为"Other(其它)", 指定客户名称并点击"Create(创建)"。服务会生成 "client ID" 和 "client secret" 代码,您可以复制它们,但这不是必须的:您可以以一个json文件的形式下载它们。点击 "Ok" 并下载用于访问本地磁盘数据的 json 文件,
在那之后,我们在服务端的准备工作就完成了,可以开发我们的应用程序了。
3. 在本地应用程序和 Google Drive 之间创建桥梁
为了解决这个任务,我已经开发了一个独立的程序(一种桥梁),它可以从 MetaTrader EA 或者指标中接收请求和数据,处理它们,再与 Google Drive 交互并把数据返回给 MetaTrader 应用程序。使用这种方法的优点,首先是 Google 提供了开发库用于使用 C# 操作 Google Drive,这使开发更加方便。其次,使用第三方应用程序来防止终端进行因外部服务带来的“资源消耗严重”的交易操作。第三,这可以使我们的应用程序不必与平台绑定,并且可以使它具有跨平台的能力,可以同时用于 MetaTrader 4 和 MetaTrader 5 应用程序。
就像我之前说过的,桥梁应用程序将会使用 Google 开发库,以 C# 语言开发。让我们在 VisualStudio 中创建 Windows Form 项目,并且使用 NuGet 加上 Google.Apis.Drive.v3 开发库。
下一步,让我们创建 GoogleDriveClass 类用于操作 Google Drive:
class GoogleDriveClass { static string[] Scopes = { DriveService.Scope.DriveFile }; //用于操作类的数组 static string ApplicationName = "Google Drive Bridge"; //应用程序名称 public static UserCredential credential = null; //认证密钥 public static string extension = ".gdb"; //所保存文件的扩展名 }
首先,让我们创建函数用于登录到服务,它将会应用之前保存的含有访问代码的 json 文件,在我的例子中,它是 "client-secret.json"。如果您已经使用不同的名称保存了文件,就在函数代码中设定它。在载入保存的数据之后,就调用服务中的异步认证函数,如果成功登录, 就在 credential 对象中保存 token 用于后来的访问。 当使用 C# 开发时,不要忘记处理异常: 如果有异常发生, credential 对象会被重置。
public bool Authorize() { using (System.IO.FileStream stream = new System.IO.FileStream("client-secret.json", System.IO.FileMode.Open, System.IO.FileAccess.Read)) { try { string credPath = System.Environment.CurrentDirectory.ToString(); credPath = System.IO.Path.Combine(credPath, "drive-bridge.json"); credential = GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.Load(stream).Secrets, GoogleDriveClass.Scopes, "example.bridge@gmail.com", CancellationToken.None, new FileDataStore(credPath, true)).Result; } catch (Exception) { credential = null; } } return (credential != null); }
当操作 Google Drive 时, 我们的 "桥梁" 应当执行两个功能: 把数据写到磁盘中以及从所需文件中读取它。让我们更加详细地讨论它们。为了实现这样看起来简单的功能,我们还是需要写多个过程,原因是 Google Drive 的文件系统和我们熟悉的不同,在这里,文件的名称和扩展名是各自独立的记录,只是用于保持显示功能,实际上,当保存的时候,在存储中每个文件都被赋予唯一的ID,这样,用户可以使用相同的名称和扩展名保存不限数量的文件,所以,在访问文件之前,我们需要知道它在云存储中的ID。为此,要载入盘中所有文件的列表并挨个把它们的名称与指定名称作比较。
GetFileList 函数就是负责取得文件列表的,它会返回 Google.Apis.Drive.v3.Data.File 类的列表。让我们使用之前下载的开发库中的 Google.Apis.Drive.v3.DriveService 类来从 Google Drive 中取得文件列表,当初始化类的时候,我们向它传入登录时取得的令牌以及我们项目的名称,结果的列表保存在返回的 result 变量中。如果有异常发生,该变量会重置为0。如有必要,我们应用程序中的其它函数会请求和处理该文件列表。
using File = Google.Apis.Drive.v3.Data.File; public IList<File> GetFileList() { IList<File> result = null; if (credential == null) this.Authorize();