了解使用 Google 登录

Understanding Sign In with Google

我正在尝试实施 Google Sign in

我的 index.php 文件是这样的:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<script src="https://accounts.google.com/gsi/client" async defer></script>

<meta http-equiv="expires" content="0"/>         
<meta http-equiv="Last-Modified" content="0">
<meta http-equiv="Cache-Control" content="no-cache, mustrevalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<script src="files/jquery-3.3.1.min.js"></script>


<script type='text/javascript'>

function handleCredentialResponse(response) {
    console.log(response.credential);//ok, long string displayed in the console

    $.ajax({
        url: "signin.php",
        type: "POST",
        dataType: 'json',
        data: { 
            idtoken: response.credential
        },
        success: function(reply_data) {
            $("#MainContainer").html(reply_data.Comentario);
        },
        error: function() {
            $("#MainContainer").html('danger...');
        }
    });             
}
</script>   
</head>
<body>
    <div id="g_id_onload"
         data-client_id="my_id_client_number.apps.googleusercontent.com"//here the proper Client ID
         data-callback="handleCredentialResponse">
    </div>
    <div class="g_id_signin" data-type="standard"></div>

    <div id="MainContainer"></div>

</body>
</html>

可以看出,我将凭据发送到 signin.php 文件,我想知道谁在尝试访问我的网站,以检查是否允许(检查数据库) .

但是为此,我需要解码凭证 (这是我的问题)

signin.php文件是这样的:

<?php
session_start();
require_once 'vendor/autoload.php';
use \Firebase\JWT\JWT;

$credencial = $_POST['idtoken'];
$key = base64_encode("xxxxxxxxxxxxxxxx");//(The Client secret from Google console)
$decoded = JWT::decode($credencial, $key, array('HS256'));
$decoded_array = (array) $decoded;

$Comentario=print_r($decoded, true);


$data = array(
    'Comentario' => $Comentario
);
echo json_encode($data);//Send response
?>

如果我理解正确,当用户尝试登录时,google 会重新设置包含密钥的凭据。所以你需要知道解密凭据的密钥。

那个键是哪个?

我尝试使用来自 Google 控制台的客户端密码(signin.php 文件,上面)。

我也尝试根据以下代码获取public密钥(成立here):

$refresh = false;
if (file_exists('oauthkey')) {
   $age = time() - filemtime('oauthkey');
   if ($age > 20000)
      $refresh = true;   
} else
   $refresh = true;

if ($refresh) {
   $oauthKey = file_get_contents('https://www.googleapis.com/oauth2/v1/certs')
      or die('Failed to retrieve google public key.');
   $keyFile = fopen('oauthkey', 'w') or die ('Failed to open public key file for writing.');
   fwrite($keyFile, $oauthKey);
   fclose($keyFile);
} else {
   $keyFile = fopen('oauthkey', 'r') or die ('Failed to open public key file for reading.');
   $oauthKey = fread($keyFile, 5000) or die ('Failed to read from public key file.');
   fclose($keyFile);   
}
$oauthKey = json_decode($oauthKey, true); // get key from Google in Array


$decoded = JWT::decode($credencial, $oauthKey, array('HS256'));

但是无法解码凭据。

所以我的两个问题是:

  1. 逻辑对吗?我的意思是:google 发送带有用户数据的凭据,该凭据是使用密钥构建的,您必须知道密钥才能对其进行解码。

  2. 使用哪个键?

  1. 你的逻辑有点不对,原因见2)的答案。

  2. 解码 ID 令牌不需要密钥,只需要您的客户端 ID。您的客户端 ID 不是秘密,它毕竟嵌入在您的 HTML 或 JS 中。

ID 令牌是由 Google 签名的 JWT 和 base64 编码,用于在网络上安全传输。它没有加密,因此不需要密钥来解码。 JWT 签名使您能够通过根据已发布的签名密钥(证书)验证签名来验证 ID 令牌是否来自 Google。

Google 提供了一个 PHP library,我强烈建议您查看并使用它来帮助解码和验证 ID 令牌。你最终会得到一个像这样的小片段 PHP 库:

require_once 'vendor/autoload.php';

// Get $id_token via HTTPS POST.

$client = new Google_Client(['client_id' => $CLIENT_ID]);  // Specify the CLIENT_ID of the app that accesses the backend
$payload = $client->verifyIdToken($id_token);
if ($payload) {
  $userid = $payload['sub'];
  // If request specified a G Suite domain:
  //$domain = $payload['hd'];
} else {
  // Invalid ID token
}