【问题标题】:Google Calendar API v3 - authenticate with hardcoded credentialsGoogle Calendar API v3 - 使用硬编码凭据进行身份验证
【发布时间】:2023-03-30 01:06:02
【问题描述】:

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

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

我曾想过以编程方式获取 OAuth 令牌,但这迟早会失败,因为 OAuth 对话框可以使用验证码。

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

【问题讨论】:

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


    【解决方案1】:

    您需要同时使用开发人员密钥(API 密钥)和 OAuth2。开发人员密钥验证谁编写了软件,并用于配额之类的事情,配额是基于每个开发人员而不是每个用户。 OAuth2 用于用户身份验证,需要访问非公开日历。

    OAuth2 有一个更新令牌,您可以从中生成会话令牌,这意味着您无需通过屏幕抓取 OAuth 屏幕来获得身份验证。为此,我会编写一个小命令行应用程序,或者您使用一个单独的 PHP 页面。

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

    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 的调用。此状态可以多次使用,直到过期,然后可以刷新。当您以您自己而不是用户身份验证您的应用程序时,此 AuthorisationState 可以由您的所有会话共享。当前的 AuthorisationState 和刷新令牌都应该安全地保存在您的服务器上,并且永远不会发送给客户端,如果您曾经将它们作为响应的一部分发送,那么您的客户端将拥有与您的代码应用程序相同的权限

    【讨论】:

      【解决方案2】:

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

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

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

      然后,激活日历。

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

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

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

      现在您已配置访问权限。现在,您将需要一些代码。要获得它们:

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

      范围:https://www.google.com/calendar/feeds/(如果您想访问日历 API。您可以在 OAuth 2.0 Playground 找到其他 API)

      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”之间。

      和之前一样,复制以下代码,并将变量放在适当的位置(代码字段是身份验证代码)。 执行,结果为“Refresh Token”。

      <?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 在他的博客中的一篇文章给了我解决方案。所有的功劳都归他。我无法链接它,因为我没有足够的“声誉”。

      【讨论】:

      • 我使用这种方法将视频上传到 Youtube,它就像一个魅力。无需要求用户进行身份验证!非常感谢!
      • 谢谢罗杰,这对我帮助很大。这应该是公认的答案,因为它更详细且专注于 php。
      • 现在,要获取刷新令牌,我需要在获取身份验证码 (developers.google.com/identity/protocols/…) 时发送“access_type:offline”。 refresh_token 是永久可用还是在某个时间后过期?
      • 永远是一个非常强烈的词!但是你只需要做一次,几年前我就有脚本在运行。
      • 我创建了一个Web Application OAuth Client Id,因为没有Installed application 选项。我按照这些步骤操作,我能够获得 身份验证代码。但要获得刷新令牌,我在echo $token-&gt;refresh_token . "\n"; 行收到Notice: Trying to get property of non-object 错误。如果有人可以查看my question,那就太好了。因为只剩下一个月的时间来完成我的最后一个研究生项目。 :(
      【解决方案3】:

      也可以与 Google php 库一起使用。 $client-&gt;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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-12
        • 2013-07-23
        相关资源
        最近更新 更多