我正在开发用于从Google Analytics(分析)帐户获取其他数据的模块。 Google要获取此数据,需要access_token。 这是我到目前为止所管理的
if (isset($_GET['code'])) {
// try to get an access token
$code = $_GET['code'];
$url = 'https://accounts.google.com/o/oauth2/token';
$params = array(
"code" => $code,
"client_id" => "559825975819-881lg83vs8feo70v5unqa8kfoijuvfnn.apps.googleusercontent.com",
"client_secret" => "vj4UNNItAJocX4RkNaD_3DQ4",
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"access_type" => "offline",
"grant_type" => "authorization_code"
);
$ch = curl_init();
curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url);
curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
$data = (json_decode($output, true));
$access_token_var = $data['access_token'];
echo $access_token_var;
} else {
$url = "https://accounts.google.com/o/oauth2/auth";
$params = array(
"response_type" => "code",
"client_id" => "559825975819-881lg83vs8feo70v5unqa8kfoijuvfnn.apps.googleusercontent.com",
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"scope" => "https://www.googleapis.com/auth/analytics",
"access_type" => "offline",
"approval_prompt" => "force"
);
$request_to = $url . '?' . http_build_query($params);
header("Location: " . $request_to);
}
我正在获取access_token,它在所需的变量中回显。但是我想在后台流程中获取分析的其他数据(例如,当客户下订单并单击订单按钮时),但是每次我需要新的access_token时,都需要使用我的Google帐户进行授权,因此,网站上的每个客户都需要为此,尽管事实是我设置了“ access_type” =>“ offline”。怎么了?还是我的API应用有问题?
答案 0 :(得分:7)
访问令牌在短时间后过期。您需要在每次访问令牌到期时刷新访问令牌。
https://developers.google.com/identity/protocols/OAuth2WebServer
访问令牌会定期过期。如果您请求脱机访问与该令牌关联的范围,则可以刷新访问令牌而无需提示用户许可(包括不存在该用户时)。
您无需刷新即可亲自访问令牌。您可以使用Goggle php库https://github.com/googleapis/google-api-php-client,以便它可以自动刷新令牌。这是一个取自Google网站的示例。
$client = new Google_Client();
$client->setAuthConfig('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$drive = new Google_Service_Drive($client);
$files = $drive->files->listFiles(array())->getItems();
echo json_encode($files);
} else {
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
如果您不想或不能使用Google Php库,则当您将访问令牌交换授权码时,Google的授权服务器会返回刷新令牌。然后,如果访问令牌过期(或在任何其他时间),则可以使用刷新令牌来获取新的访问令牌。您可以使用与通过curl获取访问令牌相同的方式,但是要使用不同的参数。
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded
client_id=<your_client_id>&
client_secret=<your_client_secret>&
refresh_token=<refresh_token>&
grant_type=refresh_token
答案 1 :(得分:0)
访问令牌会定期过期。如果您请求脱机访问与该令牌关联的范围,则可以刷新访问令牌而无需提示用户许可(包括不存在该用户时)。
如果您使用Google API Client Library,则只要将对象配置为脱机访问,客户端对象就会根据需要刷新访问令牌。
如果不使用客户端库,则需要在redirecting the user to Google's OAuth 2.0 server时将access_type HTTP查询参数设置为离线。在这种情况下,当您exchange an authorization code输入访问令牌时,Google的授权服务器会返回刷新令牌。然后,如果访问令牌过期(或在任何其他时间),则可以使用刷新令牌来获取新的访问令牌。
请求离线访问是任何在用户不存在时需要访问Google API的应用程序的要求。例如,在预定时间执行备份服务或执行操作的应用需要能够在用户不存在时刷新其访问令牌。默认的访问方式称为在线。
服务器端Web应用程序,已安装的应用程序和设备都在授权过程中获取刷新令牌。刷新令牌通常不在客户端(JavaScript)Web应用程序中使用。
对于使用PHP的Google API客户端库并寻求脱机访问和刷新令牌的用户,在撰写本文时,请注意文档中显示的示例不正确。
当前显示:
$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
$client->setIncludeGrantedScopes(true); // incremental auth
来源:https://developers.google.com/identity/protocols/OAuth2WebServer#offline
所有这些都很棒-除了一件之外
$client->setApprovalPrompt("consent");
经过一番推理,我将此行更改为以下内容,并且一切正常
$client->setPrompt("consent");
这很有意义,因为使用HTTP请求将其从#approval_prompt = force#更改为#prompt = consent#。因此,将setter方法从setApprovalPrompt更改为setPrompt遵循自然的惯例-但它不在DOCS中!!!我至少发现了。