问题描述
我目前有一个应用程序,要求我从客户端和服务器调用google drive api。现在,我已经在前端使用auth 2.0对用户进行了身份验证,可以上传文件了。
async function uploadDocgoogle() {
// get file
const fileChooser = document.getElementById('config-file-upload');
const file = fileChooser.files[0];
console.log("file",file);
const fileMetaData = {
'name': file.name,'mimeType': file.type
};
var accesstoken = gapi.auth.getToken().access_token; // Here gapi is used for retrieving the access token.
await setGoogleAPIToken(accesstoken);
console.log(accesstoken);
var form = new FormData();
form.append('Metadata',new Blob([JSON.stringify(fileMetaData)],{type: 'application/json'}));
form.append('file',file);
var xhr = new XMLHttpRequest();
xhr.open('post','https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id');
xhr.setRequestHeader('Authorization','Bearer ' + accesstoken);
xhr.responseType = 'json';
xhr.onload = () => {
console.log(xhr.response.id); // Retrieve uploaded file ID.
console.log(xhr);
};
xhr.send(form);
}
var ScopES = 'https://www.googleapis.com/auth/drive';
var authorizeButton = document.getElementById('config-google-test');
/**
* On load,called to load the auth2 library and API client library.
*/
function handleClientLoad() {
gapi.load('client:auth2',initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient() {
gapi.client.init({
apiKey: API_KEY,clientId: CLIENT_ID,discoveryDocs: disCOVERY_DOCS,scope: ScopES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
//authorizeButton.onclick = handleAuthClick;
},function(error) {
appendPre(JSON.stringify(error,null,2));
});
}
/**
* Called when the signed in status changes,to update the UI
* appropriately. After a sign-in,the API is called.
*/
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
console.log("Logged In");
} else {
console.log("Logged Out");
}
}
/**
* Sign in the user upon button click.
*/
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
/**
* Sign out the user upon button click.
*/
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
现在,我需要从用NodesJS编写的后端调用api。但是,我想使用前端已经拥有的功能来授权这些调用。在前端为呼叫生成的auth令牌似乎只是临时的,因此我认为我无法将其发送到后端以授权呼叫。我想知道是否有人知道另一种方法?我想知道是否有人还知道如何初始化Google Api以使用该令牌进行呼叫。
解决方法
尝试以下方法:
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
const SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly'];
const TOKEN_PATH = 'token.json';// You can save token in dB as well
fs.readFile('credentials.json',(err,content) => {
if (err) return console.log('Error loading client secret file:',err);
// Authorize a client with credentials,then call the Google Drive API.
authorize(JSON.parse(content),listFiles);
});
function authorize(credentials,callback) {
const {client_secret,client_id,redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id,client_secret,redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH,token) => {
if (err) return getAccessToken(oAuth2Client,callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getAccessToken(oAuth2Client,callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',scope: SCOPES,});
console.log('Authorize this app by visiting this url:',authUrl);
const rl = readline.createInterface({
input: process.stdin,output: process.stdout,});
rl.question('Enter the code from that page here: ',(code) => {
rl.close();
oAuth2Client.getToken(code,token) => {
if (err) return console.error('Error retrieving access token',err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH,JSON.stringify(token),(err) => {
if (err) return console.error(err);
console.log('Token stored to',TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
function listFiles(auth) {
const drive = google.drive({version: 'v3',auth});
drive.files.list({
pageSize: 10,fields: 'nextPageToken,files(id,name)',},res) => {
if (err) return console.log('The API returned an error: ' + err);
const files = res.data.files;
if (files.length) {
console.log('Files:');
files.map((file) => {
console.log(`${file.name} (${file.id})`);
});
} else {
console.log('No files found.');
}
});
}
如果要使用前端,可以简化'getAccessToken'。当您获得一个帐户授权给Google时。 Google会退还给您一个验证码。在此函数中使用该代码。这将实现您的目标。
rl.question('Enter the code from that page here: ',(code) => {
rl.close();
oAuth2Client.getToken(code,token) => {
if (err) return console.error('Error retrieving access token',err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH,(err) => {
if (err) return console.error(err);
console.log('Token stored to',TOKEN_PATH);
});
callback(oAuth2Client);
});
});
,
您可以在NodeJS中使用通行证来集成google auth 2.0,然后在前端使用它来认证和登录用户。用户登录后,您将获得带有其他用户数据(名称,电子邮件等)的令牌(来自google auth)。然后您可以将其存储在数据库中(或服务器变量/ json文件)。
现在,您可以使用会话来保留用户状态,或者简单地调用带有附加令牌的必需的api(在前端,React Hooks中保留其状态?还是cookie可以正常工作),并且可以验证它是哪个用户。 / p>
这是一个粗略的解决方案。但是我以类似的方式使用它。