如何使用Google Drive API永久授权用户帐户将文件上传到您的云端硬盘?

时间:2018-02-13 09:07:30

标签: php google-api google-drive-api google-oauth google-api-php-client

我正在尝试让我的网络应用程序使用专用的电子邮件帐户通过API将文件上传到谷歌驱动器。问题在于它一直要求潜在用户验证我为其准备的帐户,这正是我试图阻止其需要的。

我遇到的任何解决方案都指示我使用刷新令牌以确保帐户保持授权。这仍然存在这样的问题:在第一次使用时,用户必须验证所述帐户。使用刷新令牌在本地保存访问令牌不起作用,因为它仍然强制新用户进行身份验证。 下面的代码段显示了用于验证的代码。

class AccessDrive
{
    private $client;

    //initialize the client data provided on the call of the function
    private function initClient($scopes, $clientsecret, $returnUrl)
    {
        $client = new Google_Client();
        try{$client->setAuthConfig($clientsecret);}catch(Google_Exception $e){echo $e;}
        $client->setClientId(CLIENT_ID);
        $client->setApplicationName(APPLICATION_NAME);
        $client->setAccessType('offline');
        //$client->setApprovalPrompt('force');
        $client->setIncludeGrantedScopes(true);   // incremental auth
        foreach ($scopes as $scope) { 
            $client->addScope($this->getScope($scope)); //assume one or multiple from the google drive scopes
        }
        $client->setRedirectUri( $returnUrl);
        return $client;
    }

    public function Login()
    {
        if (!$_SESSION['code']) {
            $auth_url = $this->client->createAuthUrl();
            header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
        } else {
            error_reporting(-1 & ~E_WARNING);
            $this->client->authenticate($_SESSION['code']);
        }
        return false;
    } 

    public function __construct($returnUrl, $scopes, $clientSecret)
    {
        $this->client = $this->initClient($scopes, $clientSecret, $returnUrl);
        $this->Login();
    }
}
?>

如何确保应用程序不需要提示用户进行身份验证,在用户应该访问的功能之外保持身份验证?

- >编辑: 在尝试通过DaImTo实现建议的方法之后,以下代码生成Google_Service_Exception,声明客户端未经授权使用此方法检索访问令牌。我不确定哪里出错了。

class AccessDrive
{
    private $client;

    public function __construct( $scopes, $credentials, $email, $toImpersonate )
    {
        putenv( "GOOGLE_APPLICATION_CREDENTIALS=".$credentials);
        $scopelist =[];
        foreach ($scopes as $scope) {
            array_push($scopelist, $this->getScope($scope));
        }
        $client = new Google_Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope($scopelist);
        $client->setSubject($toImpersonate);
        $this->client = $client;
    }

- >编辑: 如果你投票,我想知道为什么这样我可以改善我当前和未来的问题。

1 个答案:

答案 0 :(得分:1)

您目前正在使用Oauth2进行身份验证。 Oauth2允许您请求用户访问他们的谷歌驱动器帐户。假设他们授予您访问权限,您将获得一个访问令牌,允许您访问他们的数据一小时。如果您请求离线访问,您将获得一个刷新令牌,当访问令牌到期时,您可以使用该令牌来请求新的访问令牌。

在您的情况下,因为您试图访问自己的驱动器帐户,我总是认为您需要使用服务帐户。服务帐户已获得批准,您可以在其上共享您的Google云端硬盘帐户中的文件夹,只要您不删除权限,它就可以访问该驱动器帐户。我有一篇关于服务帐户如何运作的帖子Google developer for beginners service account

示例:

// Load the Google API PHP Client Library.
require_once __DIR__ . '/vendor/autoload.php';
// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');
/**
 * Gets the Google client refreshing auth if needed.
 * Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
 * Initializes a client object.
 * @return A google client object.
 */
function getGoogleClient() {
    return getServiceAccountClient();
}
/**
 * Builds the Google client object.
 * Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
 * Scopes will need to be changed depending upon the API's being accessed. 
 * array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
 * List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
 * @return A google client object.
 */
function getServiceAccountClient() {
    try {   
        // Create and configure a new client object.        
        $client = new Google_Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope([YOUR SCOPES HERE]);
        return $client;
    } catch (Exception $e) {
        print "An error occurred: " . $e->getMessage();
    }
}

代码从我的示例项目serviceaccount.php

中删除

用法:

require_once __DIR__ . '/vendor/autoload.php';
session_start();
require_once __DIR__ . '/ServiceAccount.php';     
$client = getGoogleClient();
$service = new Google_Service_Drive($client); 

然后,您的所有请求都会使用$service

发送