如何在服务器应用中登录Google API并使用Google Plus?

时间:2017-07-30 16:09:21

标签: google-api google-plus google-api-php-client google-oauth2

最初的任务就像这样简单:从Google+信息页获取最新信息。

现在花了3天时间才发现互联网上的所有示例都显得过时或错误或无效。 Google开发人员文档也没有提供太多帮助,每个新的令人困惑的文档页面都会越来越复杂。所以,伙计们,我放弃了。

首先,我尝试实施OAuth 2.0程序,该程序在其文档(https://developers.google.com/identity/protocols/OAuth2WebServer)中有记录。正如其标题所暗示的那样,它正是从服务器应用程序连接。我跟着它,乍一看,它工作:我得到了后面的电话,成功通过认证,获取了访问令牌并存储了它并进行了简单的调用以获取帖子。

// Initialization

$this->googleClient = new Google_Client();
$this->googleClient->setAuthConfig(Json::decode($config->get('client_json')));
$this->googleClient->setAccessType('offline');
$this->googleClient->setIncludeGrantedScopes(TRUE);
$this->googleClient->addScope('https://www.googleapis.com/auth/plus.me');
$this->googleClient->setRedirectUri(Url::fromRoute('mymodule.gplus.callback')->setAbsolute()->toString());

// The callback

$client->authenticate($code);
$accessToken = $client->getAccessToken();

(这里唯一看起来很傻的东西 - 是范围。如果我只需要从公共页面阅读公开帖子,我不知道我应该要求的范围,所以我只选择了第一个随机条目相关。)

正如我所说,我得到了令牌并可以取回我的帖子:

// Using Google_Service_Plus

$this->client()->setAccessToken($access_token);
$this->googleServicePlus = new Google_Service_Plus($this->client($reset));
$this->googleServicePlus->activities->listActivities($endpoint, 'public', ['maxResults' => 1]);

但是1小时后它就停止工作,声称令牌已过时或者其他东西需要刷新。这是showstopper:我发现无法刷新令牌。来自$response的{​​{1}}不再返回刷新令牌(虽然在其他答案中已经多次提及),所以我甚至没有办法刷新它。

我尝试在库中挖掘(来自我的authenticate()composer.json),并发现"google/apiclient": "^2.0"方法实际上已弃用,因此很少有其他方法似乎与令牌一起使用。我尝试了authenticate(),要求提供一些应用程序默认凭据 ...这导致我们在此处描述完全不同的主题和身份验证方式:https://developers.google.com/identity/protocols/OAuth2ServiceAccount

那么我应该放弃我所做的一切,现在实施新的东西吗?我怎么能做这个简单的获取新闻的任务?

很抱歉这个问题很长。

1 个答案:

答案 0 :(得分:0)

您正在遵循的流程很好。您遇到的问题是刷新令牌。虽然官方文件说明:

  

如果您使用Google API客户端库,只要您将该对象配置为脱机访问,客户端对象就会根据需要刷新访问令牌。

它没有解释如何使用PHP客户端库执行此操作。这对我来说也是一个问题所以这就是我采取的方法,希望它可以帮到你。

// 1. Build the client object
$client = new Google_Client(); 
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/index.php');
$client->setAuthConfig("client_secret.json");
$client->addScope($scopes);
$client->setAccessType("offline");

我通常将访问令牌保存到会话中,因此在继续之前,我会检查访问令牌是否已保存到会话中。如果是,那么我继续检查访问令牌是否已经过期。如果是,则继续刷新访问令牌,然后继续进行API调用。

// 2. Check if the access token is already saved to session
if( isset($_SESSION["access_token"]) && ($_SESSION["access_token"]) ) {

    //set access token before checking if already expired
    $client->setAccessToken($_SESSION["access_token"]); 

    //check if access token is already expired and refresh if so
    if ($client->isAccessTokenExpired()) { 
        $refreshToken = $_COOKIE["refresh_token"]; //get refresh token
        $client->refreshToken($refreshToken); // refresh the access token
    }

    //get new access token and save it to session
    $_SESSION['access_token'] = $client->getAccessToken(); 

    // set access token after checking if already expired
    $client->setAccessToken($_SESSION["access_token"]); 

    $plusService = new Google_Service_Plus($client);  

    $optParams = array(
        "maxResults" => 5,
        "pageToken" => null
    );

    $activitiesList = $plusService->activities->listActivities("+cnn", "public", $optParams);

    $activities = $activitiesList->getItems();

    foreach ($activities as $activity ) {
        print_r($activity);
        print "<br>**********************<br>";
    }


}

如果访问令牌未保存到会话中,则表示尚未进行身份验证和授权,因此我将继续对用户进行身份验证。

// 3. Authenticate user since access token is not saved to session
else {

  if( !isset($_GET["code"]) ){ //get authorization code 

    $authUrl = $client->createAuthUrl();
    header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));

  } else { //exchange authorization code for access token

    $client->authenticate($_GET['code']); //authenticate client

    //get access token and save it to session
    $_SESSION['access_token'] = $client->getAccessToken();

    //save refresh token to a Cookie
    $refreshToken = $_SESSION["access_token"]["refresh_token"];
    setcookie("refresh_token", $refreshToken, time() + (86400 * 30), "/");

    $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/index.php';
    header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));

  }

}

请注意:出于演示目的,我在此示例中将刷新令牌保存到Cookie中;但是,众所周知,您不应将此信息保存到cookie,而应保存到安全数据库。此外,{@ 1}}方法不会被弃用,它只是方法authenticate()的别名。另一件事,你使用的范围不是愚蠢,因为你是从公共页面获取信息,根据文档here here ,我直觉说我应该只允许访问了解你在Google上的身份 fetchAccessTokenWithAuthCode()