Google Calendar API v3 - 使用硬编码凭据进行身份验证

时间:2011-11-24 13:15:53

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

我正在编写一个PHP应用程序,它应该允许用户将某些事件添加到私人Google日历中。日历由我拥有,我需要一种方法让PHP使用固定凭据与日历API进行通信(每个人都可以使用网站上的表单添加事件,但日历本身不公开)。

根据我的阅读,可以在v1 API中使用ClientLogin。但是,在v3 API中,可用选项是OAuth2.0或API密钥。使用API​​密钥似乎不起作用,因为它只能用于不需要授权的请求,而OAuth似乎也不正确,因为用户不应该访问他们自己的日历,而是我的日历应用程序使用。

我考虑以编程方式获取OAuth令牌,但由于OAuth对话框可以使用验证码,因此迟早会中断,因为OAuth对话框可以使用验证码。

这似乎是一个标准的用例 - 一个允许用户以某种预定义的方式与单个日历交互的Web应用程序 - 但我找不到任何关于如何在v3 API中实现它的文档。任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分:28)

我找到了一个解决方案,我认为这是你想要做的“官方”。

首先,您必须激活Google API“已安装应用程序的客户端ID”。

转到Google API控制台并创建项目。

然后,激活日历。

转到“API访问”选项,然后使用“创建OAuth 2.0客户端”按钮。

为产品命名(和徽标,如果需要)。点击“下一步”。

选择“已安装的应用程序”选项,然后单击“创建客户端ID”。

现在您可以配置您的访问权限了。现在,您需要一些代码。获得它们:

*“验证码”。要获得它,您需要以下信息:

SCOPE:https://www.google.com/calendar/feeds/(如果您想访问日历API。还有其他人可以在OAuth 2.0 Playground找到它们)

CLIENT_ID:您可以在Google API控制台的API访问部分找到它。

REDIRECT_URI:把它放在同一个地方。

现在,将以下代码复制到一个文件中,将值放入变量中,执行代码(php -q script_name.php),然后转到打印的URL。

<?php
$scope         =   '';
$client_id      =   '';
$redirect_uri   =   '';

$params = array(
                    'response_type' =>   'code',
                    'client_id'     =>   $client_id,
                    'redirect_uri'  =>   $redirect_uri,
                    'scope'         =>   $scope
                    );
$url = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query($params);        
echo $url."\n";
?>

网页会要求您允许访问。这样做,您将获得一个代码,这是您的验证码。

*“刷新代码”。为了得到它,你需要:

您之前使用的数据,以及API控制台中的“客户端密码”代码,位于“客户端ID”和“重定向URI”之间。

如前所述,复制以下代码,并将变量放在适当位置(代码字段为验证码)。 执行,结果是“刷新令牌”。

<?php
$url = 'https://accounts.google.com/o/oauth2/token';
$post_data = array(
                    'code'          =>   '',
                    'client_id'     =>   '',
                    'client_secret' =>   '',
                    'redirect_uri'  =>   '',
                    'grant_type'    =>   'authorization_code',
                    );
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);
$token = json_decode($result);

echo $token->refresh_token . "\n";
?>

此时此刻,您拥有所需的一切。如果有一天您更改了验证码,请务必小心。你必须得到新钥匙。

要访问日历服务,请在此处举例: 使用前更改变量值。 此示例获取主日历事件,但您可以更改日历API中的任何地址(http://code.google.com/intl/ca/apis/calendar/v3/getting_started.html#background_operations

    <?php
    $scope         =   'https://www.google.com/calendar/feeds/';
    $client_id      =   '';
    $client_secret  =   '';
    $redirect_uri   =   '';


    $refresh_token  =   '';

    $token_url = 'https://accounts.google.com/o/oauth2/token';
    $post_data = array(
                        'client_secret' =>   $client_secret,
                        'grant_type'    =>   'refresh_token',
                        'refresh_token' =>   $refresh_token,
                        'client_id'     =>   $client_id
                        );
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $token_url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $result = curl_exec($ch);
    $token_object = json_decode($result);
    $access_token = $token_object->access_token;

    // Get the results
    $rest_url = 'https://www.googleapis.com/calendar/v3/calendars/primary/events';
    $header = "Authorization: OAuth " . $access_token;

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_HTTPHEADER, array($header));
    curl_setopt($ch, CURLOPT_URL, $rest_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $rest_result = curl_exec($ch);

    print_r(json_decode($rest_result));
    ?>

首先,脚本要求“访问令牌”,有效期为一小时。然后,脚本获取REST服务(日历范围内的任何一个),在标头中发送访问令牌。 为了在脚本上提供最佳速度,最好将访问令牌存储在缓存中,直到它超过3600秒。这样,脚本就可以避免两次调用之一。

提示:

访问OAuth 2.0 Playground,了解OAuth流程中发送的所有信息。它给了我很多帮助

Eric Nagel在他博客中的帖子给了我解决方案。所有的优点都归于他。我无法联系它,因为我没有足够的“声誉”。

答案 1 :(得分:13)

您需要同时使用开发人员密钥(API密钥)和OAuth2。开发人员密钥对编写软件的人进行身份验证,并用于配额等基于每个开发人员而非每个用户的事项。 OAuth2用于用户身份验证,需要访问非公开日历。

OAuth2有一个续订令牌,您可以从中生成会话令牌,这意味着您无需屏幕截取OAuth屏幕即可进行身份验证。为了得到这个,我会编写一个小命令行应用程序,或者你使用一个PHP页面。

  1. Google Api Console下转到API访问
  2. 生成新的客户端ID并选择已安装的应用程序(因为您将对您的服务器进行身份验证,因为您不是您的用户)
  3. 使用控制台应用程序或使用OAuth和您的Google帐户(包含您要访问的日历的帐户)进行身份验证的PHP页面之一
  4. 在从身份验证返回时,应该有续订令牌(称为续订或刷新或类似的东西)。保存此字符串并将其提供给您的PHP站点。
  5. 当您需要访问该服务时,您的OAuth库应进行续订/刷新调用。下面有一个使用.Net的例子。

  6. private IAuthorizationState CreateAuthorization(NativeApplicationClient arg)
     {
       // Get the auth URL:
       IAuthorizationState state = new AuthorizationState(new[] { AdsenseService.Scopes.AdsenseReadonly.GetStringValue() });
       state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
       if (refreshToken.IsNotNullOrEmpty()) // refreshToken you stored in step 4
       {
         try
         {
           state.RefreshToken = refreshToken;
           if (arg.RefreshToken(state))     // This is calling out to the OAuth servers with the refresh token getting back a session token, returns true if successful.
           {
             if (state.RefreshToken != refreshToken) // if the refresh token has changed, save it.
             {
               PersistRefreshToken(authorization.RefreshToken);
             }
             return this.authorization = state; // Retain the authorization state, this is what will authenticate your calls.
           }
         }
         catch (ProtocolException ex) {...}
    

    现在已更新的AuthorisationState可用于验证您对API所做的调用。这个状态可以多次使用,直到它到期,然后可以刷新。当您将自己的应用程序身份验证为自己而不是用户时,所有会话都可以共享AuthorizationState。当前AuthorizationState和刷新令牌都应安全地保存在您的服务器上,并且永远不会发送到客户端,如果您曾将这些作为响应的一部分发送,您的客户端将具有与您的代码应用程序相同的权限

答案 2 :(得分:2)

也可以与Google php库一起使用。 $client->setAccessToken()函数的访问令牌必须按以下方式格式化:

$at= '{"access_token":"' . $access_token . '",' .
      '"token_type":"Bearer",' .
      '"expires_in":3600,' .
      '"refresh_token":"' . $refresh_token . '",',
      '"created":' . time() . '}';

$access_token是您找到的访问令牌,$refresh_token是刷新令牌。使用无用的simple.php google示例进行测试。

身份验证只是:

$client->setAccessToken($at);