使用Google JavaScript API进行身份验证

时间:2017-10-13 12:56:41

标签: javascript php google-api gmail-api google-api-php-client

我正在尝试使用Gmail API访问网络应用程序中的电子邮件。我在https://developers.google.com/gmail/api/quickstart/php尝试过这个例子并且工作正常。现在我想使用javascript API获取访问令牌并在上面的示例中使用。

gapi.auth2.authorize({
  client_id: 'CLIENT_ID.apps.googleusercontent.com',
  scope: 'email profile openid',
  response_type: 'id_token permission'
}, function(response) {
  if (response.error) {
    // An error happened!
    return;
  }
  // The user authorized the application for the scopes requested.
  var accessToken = response.access_token;
  var idToken = response.id_token;
  // You can also now use gapi.client to perform authenticated requests.
});

当我在php脚本中手动添加来自javascript API的响应时,它显示错误

Uncaught exception 'LogicException' with message 'refresh token must be passed in or set as part of setAccessToken' in D:\wamp\www\gmailexample\google-api-php-client-2.2.0\src\Google\Client.php:267

以下是我正在使用的php脚本。

<?php
require_once '/google-api-php-client-2.2.0/vendor/autoload.php';


define('APPLICATION_NAME', 'Gmail API PHP Quickstart');
define('CREDENTIALS_PATH', '~/.credentials/gmail-php-quickstart.json');
define('CLIENT_SECRET_PATH', 'client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/gmail-php-quickstart.json
define('SCOPES', implode(' ', array(
  Google_Service_Gmail::GMAIL_READONLY)
));

if (php_sapi_name() != 'cli') {
  throw new Exception('This application must be run on the command line.');
}

/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient() {
  $client = new Google_Client();
  $client->setApplicationName(APPLICATION_NAME);
  $client->setScopes(SCOPES);
  $client->setAuthConfig(CLIENT_SECRET_PATH);
  $client->setAccessType('offline');

  // Load previously authorized credentials from a file.
  $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);

  $accessToken= json_decode('{"access_token":"asdfsasdfsasdfsasdfs","expires_in":2255,"expires_at":254877}', true);
  $client->setAccessToken($accessToken);

  // Refresh the token if it's expired.
  if ($client->isAccessTokenExpired()) {
    $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
  }
  return $client;
}

/**
 * Expands the home directory alias '~' to the full path.
 * @param string $path the path to expand.
 * @return string the expanded path.
 */
function expandHomeDirectory($path) {
  $homeDirectory = getenv('HOME');
  if (empty($homeDirectory)) {
    $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
  }
  return str_replace('~', realpath($homeDirectory), $path);
}

// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Gmail($client);

// Print the labels in the user's account.
$user = 'me';
$results = $service->users_labels->listUsersLabels($user);

if (count($results->getLabels()) == 0) {
  print "No labels found.\n";
} else {
  print "Labels:\n";
  foreach ($results->getLabels() as $label) {
    printf("- %s\n", $label->getName());
  }
}

请帮忙。

1 个答案:

答案 0 :(得分:1)

好的,我的朋友,这是你的解决方案。为了确保你理解这一点,我做了一个例子。首先,在工作目录中,确保您拥有Google PHP客户端库和另外两个文件。第一个应该被称为 index.php 并将以下代码粘贴到该文件中:

<html>

  <head>

    <title>JS/PHP Google Sample</title>

    <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>

    <script type="text/javascript">

      function handleClientLoad() {
        // Loads the client library and the auth2 library together for efficiency.
        // Loading the auth2 library is optional here since `gapi.client.init` function will load
        // it if not already loaded. Loading it upfront can save one network request.
        gapi.load('client:auth2', initClient);
      }

      function initClient() {
        // Initialize the client with API key and People API, and initialize OAuth with an
        // OAuth 2.0 client ID and scopes (space delimited string) to request access.
        gapi.client.init({
            apiKey: 'YOUR API KEY GOES HERE',
            clientId: 'YOUR CLIENT ID GOES HERE',
            scope: 'email profile https://www.googleapis.com/auth/gmail.readonly',
        }).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());
        });
      }

      function updateSigninStatus(isSignedIn) {
        // When signin status changes, this function is called.
        // If the signin status is changed to signedIn, we make an API call.
        if (isSignedIn) {
            $("#signout-button").show();
            $("#signin-button").hide();
            makeApiCall();
        } else {
            $("#signin-button").show();
            $("#signout-button").hide();
        }
      }

      function handleSignInClick(event) {
        // Ideally the button should only show up after gapi.client.init finishes, so that this
        // handler won't be called before OAuth is initialized.
        gapi.auth2.getAuthInstance().signIn();
      }

      function handleSignOutClick(event) {
        var host = "http://"+window.location.hostname;
        gapi.auth2.GoogleUser.prototype.disconnect();
        window.open(host, "_self");
      }

      function makeApiCall() {
        // Make an API call to the People API, and print the user's given name.       
        var accsTkn = gapi.auth2.getAuthInstance().$K.Q7.access_token;    
        var formData = new FormData();
        formData.append("access_token", accsTkn); //send access token

        $.ajax({
            url : 'listEmails.php',
            type : 'POST',
            data : formData,
            processData: false,  // tell jQuery not to process the data
            contentType: false,  // tell jQuery not to set contentType
            success : function(html) {

                $("#myLabels").append(html);

            }
        });

      }

    </script>

    <style>

        #signin-button{
            display: none;
        }

        #signout-button{
            display: none;
        }

        #myLabels{
            width: 80%;
            min-height: 350px;
        }

    </style>


  </head>

  <body>

    <center>

        <h1>Google OAuth Gmail Example with Javascript and PHP</h1><br>

        <button id="signin-button" onclick="handleSignInClick()">Sign In</button>

        <br><br><br>

        <div id="myLabels">
            Emails list: <br><br>

        </div>      

        <br><br>
        <button id="signout-button" onclick="handleSignOutClick()">Sign Out</button>

    </center>


    <script async defer src="https://apis.google.com/js/api.js" onload="this.onload=function(){};handleClientLoad()" onreadystatechange="if (this.readyState === 'complete') this.onload()">  </script>

  </body>

</html>

接下来,第二个文件应命名为 listEmails.php 并将以下代码粘贴到其中:

<?php session_start();     

require_once "path_to_php_client_lib/vendor/autoload.php"; //include php client library

//set the required parameteres
$scopes = array("https://www.googleapis.com/auth/gmail.readonly");

$client = new Google_Client(); 
$client->setRedirectUri('http://'.$_SERVER['HTTP_HOST'].'listEmails.php');
$client->setAuthConfig("client_secret.json");
$client->addScope($scopes);

$client->setAccessToken($_POST["access_token"]);
$service = new Google_Service_Gmail($client); // define service to be rquested

$pageToken = NULL;
$messages = array();
$opt_param = array("maxResults" => 5);

try {
  $messagesResponse = $service->users_messages->listUsersMessages("me", $opt_param);
  if ($messagesResponse->getMessages()) {
    $messages = array_merge($messages, $messagesResponse->getMessages());
  }
} catch (Exception $e) {
  print 'An error occurred: ' . $e->getMessage();
}

foreach ($messages as $message) {
    $msgId = $message->getId();
    $optParams = array("format" => "full");
    $uniqueMsg = $service->users_messages->get("me", $msgId, $optParams);
    print 'Message with ID: ' . $uniqueMsg->id . '<br>';
    print 'Message From: ' . $uniqueMsg->getPayload()->getHeaders()[18]->value . '<br><br>**************************<br><br>';
}


?>

了解示例: 文档here清楚地解释了

  

此OAuth 2.0流称为隐式授权流。它专为仅在用户出现在应用程序时访问API的应用程序而设计。这些应用程序无法存储机密信息。

这意味着使用Javascript身份验证流程将无法获得脱机访问权限。考虑到这一点,我们可以继续前进。

正如您可以在php脚本上看到的那样,您不需要刷新令牌,因为这将由Javascript客户端库管理;那你去...我希望这有帮助!