0x00 基本认证
这部分内容,官方文档写得很是清楚。Google 提供的 APIs 访问是基于 Oauth2.0 认证的,其流程可以大致分为以下几个步骤:
1. 客户端 App 发起认证(若用户没有登录,则需要先登录)
2. 弹出授权页面,用户点击允许后,Google 认证服务器给我们返回一个授权码(Authorization code)
3. 客户端获取到授权码以后,用授权码向认证服务器请求 Access Token
4. 服务器验证授权码无误后返回 Access Token 至客户端
5. 拿到 Access Token 以后,就可以访问 Google APIs 了(其实这里还会返回一个Refresh token)
大家直接看下面的图可能会比较好理解一点:
上面的流程只是基于第一次获取 Access Token 的情况,因为 Access Token 是有期限的,默认是1个小时,Access Token 过期之后,就需要通过 Refresh Token 来向 Google 认证服务器申请一个新的 Access token,不需要经历上面的1,2,3步。
0x01 Refresh Token 期限
Refresh Token 并不是一直有效的,在下面的几种情况下将会失效:
• 用户撤销了对应用程序的授权
• 该 Refresh Token 已超过 6 个月未使用
• 用户修改了密码,并且 Refresh Token 授权的 Scope 包含了 Gmail
• 用户账号的 Refresh Token 数量已超出最大数量
• 用户属于具有有效会话控制策略的 Google Cloud Platform 组织
目前每个用户账号每个授权凭证有 25 个 Refresh Token 的数量限制,如果超过了这个限制,当你新建一个 Refresh token 的时候将会使最早创建那个失效。一般来说,我们在经过用户授权,拿到授权码请求到 Refresh Token 后,必须把它缓存起来,以便后续更新 Access Token。
因此在实际使用时,使用 Refresh Token 来申请 Access Token 即可。
0x02 实操获取 Token
2.1 创建应用及 OAuth 客户端 ID
登录 Google,访问 https://console.cloud.google.com/cloud-resource-manager?organizationId=0
点击创建项目
项目名称可自定义。创建后进入 【API 和服务】-> 【OAuth 同意屏幕】
完成之后,进入【凭证】创建 OAuth 客户端 ID。
应用类型选择【桌面应用】-> 【创建】。 成功获取到想要的客户端 ID 和 客户端密钥。
还有两步,差点忘了。
选择【库】,搜索 【Google Drive API】-> 【启用】
2.2 获取 Authorization code
组装一下连接,放入浏览器中访问:
https://accounts.google.com/o/oauth2/auth?client_id=[Application Client Id]&redirect_uri=http://localhost&scope=[Scopes]&response_type=code
由于我这里已经登录了账号,因此直接点入账号即可。
成功获取 code。
关于常用的 Scope
Scope | 描述 |
https://www.googleapis.com/auth/drive.file | 对应用程序创建或打开的文件进行逐个访问 |
https://www.googleapis.com/auth/drive | 访问用户所有文件的完全、允许的范围。只有在严格需要的情况下,才会申请这个范围。 |
https://www.googleapis.com/auth/drive.appdata | 允许访问 应用程序数据文件夹 |
2.3 获取 Access Token 和 Refresh Token
POST 请求以下内容:
https://accounts.google.com/o/oauth2/token
httpBody:
code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code
成功获取到两个 Token。
2.4 通过 Refresh Token 获取 Access Token
由于每个 Access Token 有效时间很短。因此当 Access Token 过期后,服务器需要使用 Refresh Token 来获取新的 Access Token 。
https://accounts.google.com/o/oauth2/token
httpBody:
refresh_token={0}&client_id={1}&client_secret={2}&grant_type=refresh_token
因此我们需要将refresh_token
进行保存。
0x03 代码实现获取 Token
通过System.Diagnostics.Process.Start(url)
来启动默认浏览器进行认证。
publicvoidGetGoogleAuthorizationCode()
{
string scope ="https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.appdata";
string url =string.Format("https://accounts.google.com/o/oauth2/auth?client_id={0}&redirect_uri={1}&scope={2}&response_type=code",
HttpUtility.UrlEncode(client_id),
HttpUtility.UrlEncode(redirectUrl),
HttpUtility.UrlEncode(scope)
);
System.Diagnostics.Process.Start(url);
}
重定向 URL 是通过 HttpListener 起一个监听,也可以直接起 Socket 进行监听。这样做是为了方便获取 code。
在获取 code 后,就可以获取 Token 了。
publicstring[]GetGoogleToken(string code)
{
string[] token =newstring[]{};
string url ="https://accounts.google.com/o/oauth2/token";
string httpBody =string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",
HttpUtility.UrlEncode(code),
HttpUtility.UrlEncode(client_id),
HttpUtility.UrlEncode(client_secret),
HttpUtility.UrlEncode(redirectUrl)
);
try
{
HttpWebRequest request =(HttpWebRequest)WebRequest.Create(url);
request.Method="POST";
request.ContentType="application/x-www-form-urlencoded";
using(var writer =newStreamWriter(request.GetRequestStream()))
{
writer.Write(httpBody);
}
HttpWebResponse response =(HttpWebResponse)request.GetResponse();
using(var reader =newStreamReader(response.GetResponseStream()))
{
string result = reader.ReadToEnd();
Console.WriteLine(result);
}
}
catch(WebException ex)
{
HttpWebResponse responseEx = ex.ResponseasHttpWebResponse;
using(var reader =newStreamReader(responseEx.GetResponseStream()))
{
string result = reader.ReadToEnd();
Console.WriteLine(result);
}
Console.WriteLine();
}
return token;
}
0x04 上传流程
https://developers.google.com/drive/api/v3/reference https://developers.google.com/drive/api/v3/reference/files 由于官方已经更新至 V3 版本,但很多例子都是使用 V2 来讲述,因此这里我就直接使用 V3 版本进行演示。
4.1 [文件 -> 创建] API 要求
4.1.1 HTTP 请求
此方法通过两个单独的 URI 提供文档数据上传功能。更多详情,请参阅文件数据上传文档。
• 上传 URI,用于文档数据上传请求
POST https://www.googleapis.com/upload/drive/v3/files
• 元数据 URI,仅用于元数据请求
POST https://www.googleapis.com/drive/v3/files
4.1.2 请求参数
参数名称 | 类型 | 描述 |
必需的查询参数 | ||
uploadType | string | 对URI的上传请求的类型。如果您正在上传数据(使用URI),则此字段是必需的。如果您正在创建仅元数据文件,则不需要此字段。 - media-简单上传。仅文档数据,不上传任何元数据。 - multipart-分段上传。在一个请求中上传文档数据及其元数据。 - resumable-可恢复上传。以可恢复的方式上传文件,至少两个请求,其中第一个请求包含元数据。 |
可选查询参数 | ||
ignoreDefaultVisibility | boolean | 是否忽略域对已创建文件的默认可见性设置。(默认: false) |
includePermissionsForView | string | 是否在新的 head 版本中设置 'keepForever' 字段。(默认: false) |
ocrLanguage | string | 图像导入期间 OCR 处理的语言提示(ISO 639-1 代码)。 |
supportsAllDrives | boolean | 请求的应用程序是否同时支持“我的云端硬盘”和共享云端硬盘。(默认: false) |
useContentAsIndexableText | boolean | 是否将上传的内容用作可索引文本。(默认: false) |
4.1.3 请求正文
参数名称 | 类型 | 描述 |
name | string | 文件的名称。这在文件夹中不一定是唯一的。 |
description | string | 文件的简短描述 |
这些参数都是可选参数
4.2 上传类型的选择
从上述的请求参数 uploadType 来看,可以执行三种类型的上传:
1. 简单上传 ( uploadType=media):使用此上传类型可快速传输小型文件(5 MB 或更少),而无需提供元数据。
2. 分段上传 ( uploadType=multipart):使用此上传类型可在单个请求中快速传输小文件(5 MB 或更少)和描述文件的元数据。
3. 可恢复上传 ( uploadType=resumable):对于大文件(大于 5 MB)以及网络中断的可能性很高的情况(例如从移动应用程序创建文件时),请使用此上传类型(可断点续传)。
写这类工具,肯定是要传输大文件的。因此毫不犹豫的选择 Resumable 类型
4.3 使用 Resumable 上传类型
此协议允许在通信故障中断数据流后恢复上传操作。它可以在发生网络故障时减少带宽使用,因为在恢复上传时,可实现断点续传。
使用可恢复上传的步骤包括:
1.
开始一个可恢复的会话
:向包含/upload/
的 URL 发起请求,如果有元数据,则一并发送。2.
保存可恢复会话 URI
:保存初始请求响应中返回的会话 URI;后续的请求将会用到该会话 URL。3.
上传文件
:将文档数据发送到可恢复会话 URI。
此外,使用可恢复上传的应用程序需要用自定义代码来实现恢复中断的上传。如果上传中断,则需要获取上传了多少数据,然后从该点继续上传。 注意:可恢复会话 URI 会在申请的一周后过期。
4.3.1 启动可恢复会话
要启动可恢复上传,需要向包含/upload/
的 URI 发出 POST 或 PUT 请求,并添加查询参数uploadType=resumable
,例如:
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable
对于这个请求,要嘛 body 为空,要嘛 body 只能包含元数据。在获取会话 URL 后,再传输要上传的实际数据。 在该请求中,需要使用以下 Http 标头:
•
X-Upload-Content-Typ
:设置为后续请求中要传输的数据的 MIME 类型。•
X-Upload-Content-Length
:设置为在后续请求中传输的上传数据的字节数。如果在此请求时长度未知,则可以省略此标头。•
Content-Type
:如果提供元数据,则根据元数据的数据类型设置。•
Content-Length
:设置为此初始请求的正文中提供的字节数。如果您使用分块传输编码,则不需要。
更多内容请参阅 API 参考,了解每种方法的可接受数据MIME 类型列表和上传文件的大小限制。
下面的示例显示了 Drive API 的分段上传请求。
POST /upload/drive/v3/files?uploadType=resumable HTTP/1.1
Host: www.googleapis.com
Authorization:Bearer your_auth_token
X-Upload-Content-Type: application/octet-stream
Content-Type: application/json; charset=UTF-8
{
"name":"MyFile.txt"
}
注意:对于没有元数据的初始可恢复更新请求,请将请求正文留空,并将Content-Length
标头设置为 0。
4.3.2 保存可恢复会话 URL
如果会话发起请求成功,API 服务器会返回 200 OK HTTP 状态码。此外,它还提供了一个 Location 标头,用于指定可恢复会话 URI。Location 标头(如下例所示)包含一个 upload_id 查询参数部分,该部分提供用于此会话的唯一上传 ID。
HTTP/1.1200 OK
X-GUploader-UploadID:ADPycduZG09xS2QEPGcpK56akP854bIgImU8tuADltGvy9OAf7Z21tOsJI00tmN8_LPiQCOo_sh4x_dLSlMAX1hkrgI
Vary:Origin,X-Origin
Pragma:no-cache
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Content-Length:0
Cache-Control:no-cache,no-store, max-age=0, must-revalidate
Content-Type: text/plain; charset=utf-8
Date:Tue,29Mar202203:35:47 GMT
Expires:Mon,01Jan199000:00:00 GMT
Location: https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=ADPycduZG09xS2QEPGcpK56akP854bIgImU8tuADltGvy9OAf7Z21tOsJI00tmN8_LPiQCOo_sh4x_dLSlMAX1hkrgI
Server:UploadServer
响应中的 Location 就是要使用的会话 URL
4.3.3 上传文件
要上传文件,请向您在上一步中获取的上传 URI 发送 PUT 请求。上传请求的格式为:
https://accounts.google.com/o/oauth2/token
httpBody:
code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code
0
发出可恢复文件上传请求时使用的 HTTP 标头包括 Content-Length。将此设置为您在此请求中上传的字节数,通常是上传文件的大小。 顺利的话,文件就上传成功了。
4.4 恢复中断的上传
如果上传请求在收到响应之前被终止了,或者收到的响应是 Http 503 Service Unavailable
,这种情况下则需要恢复中断的上传。当然你想重新传也就不说你了。
恢复中断的上传的步骤包括:
1.
状态查询
:通过向会话 URL发出一个 PUT 请求来查询所传文件的当前状态2.
获取上传的字节数
:处理来自状态查询的响应3.
上传剩余数据
:在获取已上传的字节数之后,重新读取文件,获取后续内容继续上传
PS:获取当前所传输文件的状态,这个数据也可以用来展示上传进度。
4.4.1 状态查询
对于此请求,HTTP 标头应包含一个Content-Range
标头,指示文件中的当前位置未知。例如,如果要上传的文件总长度为 2,000,000,请将 Content-Range 设置为*/2000000
。如果不知道文件的大小,则请将 Content-Range 设置为*/*
。
https://accounts.google.com/o/oauth2/token
httpBody:
code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code
1
4.4.2 获取上传的字节数
这个数是获取 4.4.1 的响应得到的。
https://accounts.google.com/o/oauth2/token
httpBody:
code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code
2
4.4.3 上传剩余数据
通过以下请求发送文件的剩余字节(从 43bytes 开始)来恢复上传。
https://accounts.google.com/o/oauth2/token
httpBody:
code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code
3
0x05 代码实现上传功能
5.1 获取 Access Token 实现
https://accounts.google.com/o/oauth2/token
httpBody:
code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code
4
5.2 上传功能实现
https://accounts.google.com/o/oauth2/token
httpBody:
code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code
5
后续的恢复中断的上传部分就不展示了。自行发挥即可
0x06 参考
1. https://developers.google.com/identity/protocols/oauth2#expiration
2. https://developers.google.com/android-publisher/authorization?hl=zh-cn
3. https://developers.google.com/android-publisher/upload?hl=zh-cn
4. https://developers.google.com/drive/api/v2/reference/files/insert#examples
5. https://github.com/advanced-rest-client/api-resource-example-document/blob/master/demo/google-drive-api/docs/upload-files.md
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...