我正在尝试授权我的应用程序与Google云端硬盘集成。 Google文档提供了基于服务器的授权和various server technologies的代码示例的详细信息。
还有一个JavaScript Google API library,它支持授权。在samples section of the wiki中有一个代码段,用于创建配置并调用authorize function。我已经将范围改为我认为驱动所需的范围:
var config = {
'client_id': 'my_client_ID',
'scope': 'https://www.googleapis.com/auth/drive.file'
};
gapi.auth.authorize(config, function() {
console.log(gapi.auth);
});
永远不会调用回调函数(是的,Google API库已加载更正)查看Java Retrieve和使用OAuth 2.0凭据示例,客户端机密似乎是一个参数,是否应该进入配置?
有没有人在JS,Drive或其他Google API中试过这个?有没有人知道调试这个问题的最佳途径,即我是否需要单步执行库并停止发牢骚?
请不要建议在服务器端进行授权,我们的应用程序完全是客户端,我不希望服务器上有任何状态(我理解这将导致令牌刷新问题)。我熟悉Google控制台中的API配置,我相信它和驱动程序SDK设置是正确的。
答案 0 :(得分:55)
可以将Google API Javascript客户端库与云端硬盘一起使用,但您必须意识到存在一些难点。
目前有两个主要问题,两个都有解决方法:
首先,如果您仔细查看Google Drive auth的工作原理,您会发现,在用户安装了Drive应用程序并尝试打开文件或使用您的应用程序创建新文件后,Drive会启动OAuth 2.0授权自动流动并将auth参数设置为 response_type = code 和 access_type = offline 。 这基本上意味着现在Drive应用程序被迫使用OAuth 2服务器端流程,这对Javascript客户端库(仅使用客户端流程)没有任何用处。
问题是:Drive启动服务器端OAuth 2.0流程,然后Javascript客户端库启动客户端OAuth 2.0流程。
这仍然有效,您只需使用服务器端代码来处理Drive服务器端流后返回的授权代码(您需要将其替换为访问令牌和刷新令牌)。 这样,只有第一个流程才会提示用户进行授权。在您第一次交换授权代码后,将自动绕过身份验证页面。
要执行此操作的服务器端示例可用in our documentation。
如果您不在服务器端流程上处理/交换授权代码,则每次尝试从云端硬盘使用您的应用时,系统都会提示用户进行身份验证。
第二个问题是我们的Javascript客户端库无法轻松上传和访问实际的Drive文件内容。你仍然可以这样做,但你必须使用自定义的Javascript代码。
阅读文件内容
检索文件元数据/文件对象时,它包含指向实际文件内容的downloadUrl
属性。现在可以使用CORS请求下载文件,最简单的auth方法是在URL参数中使用OAuth 2访问令牌。因此,只需将&access_token=...
附加到downloadUrl
,然后使用XHR或通过将用户转发到网址来获取文件。
上传文件内容
更新更新:上传端点执行现在支持CORS。
~~更新:与其他Drive API不同,上传端点不支持CORS,因此您现在必须使用以下技巧:~~
上传文件很棘手,因为它没有内置在Javascript客户端库中,你不能像this response中所描述的那样完全使用HTTP,因为我们不允许在这些API端点上进行跨域请求。因此,您必须利用我们的Javascript客户端库使用的iframe代理,并使用它将构建的多部分请求发送到Drive SDK。感谢@Alain,我们在下面有一个如何执行此操作的示例:
/**
* Insert new file.
*
* @param {File} fileData File object to read data from.
* @param {Function} callback Callback function to call when the request is complete.
*/
function insertFileData(fileData, callback) {
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var reader = new FileReader();
reader.readAsBinaryString(fileData);
reader.onload = function(e) {
var contentType = fileData.type || 'application/octet-stream';
var metadata = {
'title': fileData.fileName,
'mimeType': contentType
};
var base64Data = btoa(reader.result);
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
var request = gapi.client.request({
'path': '/upload/drive/v2/files',
'method': 'POST',
'params': {'uploadType': 'multipart'},
'headers': {
'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
},
'body': multipartRequestBody});
if (!callback) {
callback = function(file) {
console.log(file)
};
}
request.execute(callback);
}
}
要改善这一切,将来我们可能会:
/upload/...
端点上的CORS exportLinks
上的CORS 此时没有承诺:)
答案 1 :(得分:12)
我做到了。继承我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<style>
p {
font-family: Tahoma;
}
</style>
</head>
<body>
<!--Add a button for the user to click to initiate auth sequence -->
<button id="authorize-button" style="visibility: hidden">Authorize</button>
<script type="text/javascript">
var clientId = '######';
var apiKey = 'aaaaaaaaaaaaaaaaaaa';
// To enter one or more authentication scopes, refer to the documentation for the API.
var scopes = 'https://www.googleapis.com/auth/drive';
// Use a button to handle authentication the first time.
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth,1);
}
function checkAuth() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}
function handleAuthResult(authResult) {
var authorizeButton = document.getElementById('authorize-button');
if (authResult && !authResult.error) {
authorizeButton.style.visibility = 'hidden';
makeApiCall();
} else {
authorizeButton.style.visibility = '';
authorizeButton.onclick = handleAuthClick;
}
}
function handleAuthClick(event) {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
return false;
}
// Load the API and make an API call. Display the results on the screen.
function makeApiCall() {
gapi.client.load('drive', 'v2', function() {
var request = gapi.client.drive.files.list ( {'maxResults': 5 } );
request.execute(function(resp) {
for (i=0; i<resp.items.length; i++) {
var titulo = resp.items[i].title;
var fechaUpd = resp.items[i].modifiedDate;
var userUpd = resp.items[i].lastModifyingUserName;
var fileInfo = document.createElement('li');
fileInfo.appendChild(document.createTextNode('TITLE: ' + titulo + ' - LAST MODIF: ' + fechaUpd + ' - BY: ' + userUpd ));
document.getElementById('content').appendChild(fileInfo);
}
});
});
}
</script>
<script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
<p><b>These are 5 files from your GDrive :)</b></p>
<div id="content"></div>
</body>
</html>
您只需要更改:
从您的Google API控制台访问您的clientID和ApiKey:)
当然,您必须在Google API控制台上创建项目,激活Drive API并在OAuth 2.0中激活Google帐户身份验证(真的很棒!)
PS:它不能在你的电脑上本地工作,它可以在某些主机上工作,并且你必须在项目控制台上提供它的网址:)