连接 html 按钮以访问 google 的人 API
connect html button to access google's people API
我的 HTML 正文中有一个按钮,当用户单击该按钮时,它应该加载用户的 google 联系人。我已经通过 Google Cloud Platform 注册了所需的凭据和授权,但由于某种原因,我拥有的 javascript 代码无法正常工作,在 Visual studio 中的演示模式下单击按钮确实有效不要打开一个新的 window 要求我登录我的 gmail 帐户,允许网站访问我的联系人等。任何帮助 API 在我的网站上工作将不胜感激。
<button id="google-button" onclick="return auth()" style="color:white;background-color:royalblue;margin:20px;padding:5px 10px;border-style:solid;font-weight:bold">Share to all of your Google contacts</button>
<script>
function auth() {
const fs = require('fs');
const readline = require('readline');
const { google } = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/contacts.readonly'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
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 Tasks API.
authorize(JSON.parse(content), listConnectionNames);
});
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, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getNewToken(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, (err, 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 listConnectionNames(auth) {
const service = google.people({ version: 'v1', auth });
service.people.connections.list({
resourceName: 'people/me',
pageSize: 10,
personFields: 'names,emailAddresses',
}, (err, res) => {
if (err) return console.error('The API returned an error: ' + err);
const connections = res.data.connections;
if (connections) {
console.log('Connections:');
connections.forEach((person) => {
if (person.names && person.names.length > 0) {
console.log(person.names[0].displayName);
} else {
console.log('No display name found for connection.');
}
});
} else {
console.log('No connections found.');
}
});
}
}
</script>
您的 <script>
标记中的代码是服务器端 Node.js 代码,而不是客户端 JavaScript。它不会在浏览器中运行,因为:
require('fs')
导入文件系统模块,但 Node.js. 之外不存在这样的东西
readline
和 googleapis
也是特定于节点的模块,因此它们在客户端 JS 中没有意义,如果 require
还没有,它们可能会抛出错误。
fs.readFile(...)
尝试使用 fs 模块(见上文)在特定路径读取文件,但客户端 JavaScript 无法访问文件系统。
- 从根本上说,OAuth 协商应该在服务器上处理,而不是在客户端上。通常,特权请求将使用您数据库中的数据,如果令牌存储在客户端上,则无法执行此操作。
这里的主要问题似乎是对 OAuth 是什么以及它是如何工作的混淆。这是该过程的简化分步演练:
- 用户从他们的客户端登录到外部服务。
- 外部服务生成代码(令牌)并将其发送给客户端。
- 客户端接收令牌(在回调、哈希参数等中)并将其发送到您的服务器。大多数情况下,外部服务会简单地将客户端重定向到您服务器上的 URL,并使用查询字符串中的令牌,让您从请求中获取它。
- 您的服务器将特定用户帐户的令牌存储在您的数据库中。
- 对于特权操作,您的服务器将请求发送到外部服务并包含令牌。
- 服务器接收带有令牌的请求并代表用户执行操作。
当外部服务收到带有令牌的请求时,它会查找该令牌并发现它属于特定用户。因为该用户必须已登录并授权您的应用程序才能创建令牌,所以该服务知道它应该继续执行该操作。
OAuth 令牌可能是永久性的,但更常见的是它们会在设定的时间段后过期并且必须重新生成。这意味着您应该 永远不会 使用令牌作为主键来识别用户。至于如何重新生成过期的令牌,具体细节因提供商而异。您正在使用的服务(Google,在这种情况下)将提供有关其身份验证流程如何工作以及应如何处理刷新的更多信息。
我的 HTML 正文中有一个按钮,当用户单击该按钮时,它应该加载用户的 google 联系人。我已经通过 Google Cloud Platform 注册了所需的凭据和授权,但由于某种原因,我拥有的 javascript 代码无法正常工作,在 Visual studio 中的演示模式下单击按钮确实有效不要打开一个新的 window 要求我登录我的 gmail 帐户,允许网站访问我的联系人等。任何帮助 API 在我的网站上工作将不胜感激。
<button id="google-button" onclick="return auth()" style="color:white;background-color:royalblue;margin:20px;padding:5px 10px;border-style:solid;font-weight:bold">Share to all of your Google contacts</button>
<script>
function auth() {
const fs = require('fs');
const readline = require('readline');
const { google } = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/contacts.readonly'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
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 Tasks API.
authorize(JSON.parse(content), listConnectionNames);
});
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, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getNewToken(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, (err, 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 listConnectionNames(auth) {
const service = google.people({ version: 'v1', auth });
service.people.connections.list({
resourceName: 'people/me',
pageSize: 10,
personFields: 'names,emailAddresses',
}, (err, res) => {
if (err) return console.error('The API returned an error: ' + err);
const connections = res.data.connections;
if (connections) {
console.log('Connections:');
connections.forEach((person) => {
if (person.names && person.names.length > 0) {
console.log(person.names[0].displayName);
} else {
console.log('No display name found for connection.');
}
});
} else {
console.log('No connections found.');
}
});
}
}
</script>
您的 <script>
标记中的代码是服务器端 Node.js 代码,而不是客户端 JavaScript。它不会在浏览器中运行,因为:
require('fs')
导入文件系统模块,但 Node.js. 之外不存在这样的东西
readline
和googleapis
也是特定于节点的模块,因此它们在客户端 JS 中没有意义,如果require
还没有,它们可能会抛出错误。fs.readFile(...)
尝试使用 fs 模块(见上文)在特定路径读取文件,但客户端 JavaScript 无法访问文件系统。- 从根本上说,OAuth 协商应该在服务器上处理,而不是在客户端上。通常,特权请求将使用您数据库中的数据,如果令牌存储在客户端上,则无法执行此操作。
这里的主要问题似乎是对 OAuth 是什么以及它是如何工作的混淆。这是该过程的简化分步演练:
- 用户从他们的客户端登录到外部服务。
- 外部服务生成代码(令牌)并将其发送给客户端。
- 客户端接收令牌(在回调、哈希参数等中)并将其发送到您的服务器。大多数情况下,外部服务会简单地将客户端重定向到您服务器上的 URL,并使用查询字符串中的令牌,让您从请求中获取它。
- 您的服务器将特定用户帐户的令牌存储在您的数据库中。
- 对于特权操作,您的服务器将请求发送到外部服务并包含令牌。
- 服务器接收带有令牌的请求并代表用户执行操作。
当外部服务收到带有令牌的请求时,它会查找该令牌并发现它属于特定用户。因为该用户必须已登录并授权您的应用程序才能创建令牌,所以该服务知道它应该继续执行该操作。
OAuth 令牌可能是永久性的,但更常见的是它们会在设定的时间段后过期并且必须重新生成。这意味着您应该 永远不会 使用令牌作为主键来识别用户。至于如何重新生成过期的令牌,具体细节因提供商而异。您正在使用的服务(Google,在这种情况下)将提供有关其身份验证流程如何工作以及应如何处理刷新的更多信息。