【问题标题】:How do I authenticate a service account in Google Cloud Services in PHP?如何在 PHP 中验证 Google Cloud Services 中的服务帐户?
【发布时间】:2021-09-17 14:15:09
【问题描述】:

在开发 Recaptcha Enterprise 以使用 V2“我不是机器人”复选框时,我遇到了这个错误:

致命错误:未捕获的 DomainException:无法加载默认凭据。浏览https://developers.google.com/accounts/docs/application-default-credentials了解更多信息

我点击链接并决定对此进行身份验证:

use Google\Cloud\Storage\StorageClient;

$storage = new StorageClient([
  'keyFile' => json_decode(file_get_contents($path_to_keyfile), true),
  'projectId' => 'MY_PROJECT'
]);

我找不到任何其他建议我需要做的事情更多,构造函数 API 的this link 并不建议我可以将它作为参数传递然后继续。我不想为这个项目使用环境变量,我想在代码中手动连接。我错过了什么?我可以确认我有一个有效的服务帐户。

如果有帮助,我想在我进行身份验证后尝试运行的代码是这样的:

// ==================== CAPTCHA ===================
use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient;
use Google\Cloud\RecaptchaEnterprise\V1\Event;
use Google\Cloud\RecaptchaEnterprise\V1\Assessment;
use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason;

$captcha_response = $_POST['g-recaptcha-response'];
$site_key = "123456789abc";

$client = new RecaptchaEnterpriseServiceClient();

define('SITE_KEY', $site_key);
define('TOKEN', $captcha_response);
define('PROTECTED_ACTION', 'signup');
define('PARENT_PROJECT', 'projects/MY_PROJECT');

$event = (new Event())
     ->setSiteKey(SITE_KEY)
     ->setExpectedAction(PROTECTED_ACTION)
     ->setToken(TOKEN);

 $assessment = (new Assessment())
     ->setEvent($event);

 try {
     $response = $client->createAssessment(
         PARENT_PROJECT,
         $assessment
     );

     if ($response->getTokenProperties()->getValid() == false) {
         printf('The CreateAssessment() call failed because the token was invalid for the following reason: ');
         printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason()));
     } else {
         if ($response->getEvent()->getExpectedAction() == PROTECTED_ACTION) {
             printf('The score for the protection action is:');
             printf($response->getRiskAnalysis()->getScore());
         }
         else
         {
             printf('The action attribute in your reCAPTCHA tag does not match the action you are expecting to score');
         }
     }
 } catch (exception $e) {
     printf('CreateAssessment() call failed with the following error: ');
     printf($e);
 }

【问题讨论】:

  • 代码的哪一部分产生了错误?您显示使用服务帐户初始化 Cloud Storage,但未显示在代码中使用存储客户端。在您的问题中,Google Cloud Storage 和 ReCaptcha 之间是什么关系?
  • 哇,这解释了很多。我认为由于某种原因实际上需要 CloudStorage,因为他们在这里给出了示例:cloud.google.com/docs/authentication/production 但是,我仍然不确定如何将我的服务帐户传递给 Recaptcha?例如,Storage 的 API 页面在构造函数中有keyFile,但 Recaptcha 的构造函数没有。

标签: php google-cloud-platform recaptcha


【解决方案1】:

这就是我的工作方式。感谢 John Hanley 在之前的回答中提供的帮助。该文档使我相信(无论出于何种原因)需要存储,但事实并非如此:它就像通过 credentials 参数提供密钥的路径一样简单。 不是keyFile 参数。

if (empty($_POST['g-recaptcha-response']))
die("You have failed the not-a-robot check.");

$captcha_response = $_POST['g-recaptcha-response'];

require 'composer/vendor/autoload.php';

use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient;
use Google\Cloud\RecaptchaEnterprise\V1\Event;
use Google\Cloud\RecaptchaEnterprise\V1\Assessment;
use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason;

$path_to_keyfile = "MY_PROJECT-1234567890abc.json";
$site_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

$client = new RecaptchaEnterpriseServiceClient([
  'credentials' => $path_to_keyfile,
  'projectId' => 'MY_PROJECT'
]);

define('SITE_KEY', $site_key);
define('TOKEN', $captcha_response);
define('PROTECTED_ACTION', 'signup');
define('PARENT_PROJECT', 'projects/MY_PROJECT');

$event = (new Event())
     ->setSiteKey(SITE_KEY)
     ->setExpectedAction(PROTECTED_ACTION)
     ->setToken(TOKEN);

 $assessment = (new Assessment())
     ->setEvent($event);

 try {
     $response = $client->createAssessment(PARENT_PROJECT, $assessment);

     if ($response->getTokenProperties()->getValid() == false) {
         printf('The CreateAssessment() call failed because the token was invalid for the following reason: ');
         printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason()));
         exit;
     } else {
         if ($response->getEvent()->getExpectedAction() == PROTECTED_ACTION) {
          // Closer to 1 = human, to 0 = robot.
          $bot_score = $response->getRiskAnalysis()->getScore();
          // do what you want with the score here...

         } else {
             die('The action attribute in your reCAPTCHA tag does not match the action you are expecting to score');
         }
     }
 } catch (exception $e) {
     printf('CreateAssessment() call failed with the following error: ');
     printf($e);
     exit;
 }

【讨论】:

    【解决方案2】:

    您的问题是您没有在客户端构造函数中指定要使用的服务帐户,并且系统正在回退到使用 ADC(应用程序默认凭据)。

    ADC 将检查环境变量 GOOGLE_APPLICATION_CREDENTIALS 以获取服务帐户 JSON 密钥文件。

    您可以在运行程序之前设置环境变量:

    窗户:

    set GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
    

    Linux:

    export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
    

    或者通过改变这行代码来修改你的程序:

    $client = new RecaptchaEnterpriseServiceClient();
    

    到这里:

    $options = ['keyFile' => $path_to_keyfile];
    
    $client = new RecaptchaEnterpriseServiceClient($options);
    

    注 1:

    如果您在 Google Cloud 计算机服务(如 Compute Engine、App Engine、Cloud Run 等)上运行您的程序,如果上述方法均未实现,则将使用默认服务帐户。

    注2:

    在开发过程中,另一种方法是使用 CLI 的应用程序默认凭据。使用 Google Cloud SDK CLI 运行以下命令:

    gcloud auth application-default login
    

    但是,我尚未验证 reCAPTCHA Enterprise 库是否会检查此类凭据。

    【讨论】:

    • 温馨提示:使用windows设置env var时,需要使用反斜杠`\`;)
    • @guillaumeblaquiere - 你是对的。但是,/path/to/service-account.json 是占位符(示例)而不是实际路径。在大多数情况下,Windows 现在接受 Linux 样式的路径。
    • 啊???这是windows的一次伟大进化!!!太久我不再用windows开发了!!很高兴知道!
    • 谢谢,约翰!看起来构造函数的参数实际上是credentials,而不是keyFile,如果您可以更新您的答案。 googleapis.github.io/google-cloud-php/#/docs/…
    • 在我使用 credentials 之前对我不起作用,即使我链接到你的页面也没有 keyFile 作为选项。
    猜你喜欢
    • 1970-01-01
    • 2019-01-10
    • 1970-01-01
    • 2020-06-17
    • 2017-11-03
    • 2019-04-14
    • 2022-11-08
    • 2022-01-06
    • 2018-11-25
    相关资源
    最近更新 更多