【发布时间】:2021-12-04 13:57:14
【问题描述】:
我正在实现一个 google 登录功能,该功能使用跨页面的 PHP 会话来确定用户是否实际上已登录。这在我的本地计算机上完美运行。 当我上传到我的托管服务器(可能是谷歌云)并相应地调整客户端 ID 然后正常登录时,登录过程完成,但用户被报告为未登录。一些页面刷新和/ 或单击“登录”按钮然后导致用户被识别为已登录。我假设会话变量设置不正确或设置它们有一些延迟。但是,也许还有另一个我不知道的问题(当我在本地运行服务时再次没有问题)。 我很欣赏这是一个有点模糊的问题。 我尝试使用 session_write_close() 以防会话保持打开太久,但这并没有明显的区别。
一旦用户通过google登录成功认证,一个POST页面,oauth.php读取变量并将其写入$_SESSION变量,例如:
session_start();
...
$_SESSION["auth"] = true;
$_SESSION["userId"] = $row['id']; // A SQL query and further logic either populates this field (existing user) or leaves it blank (new user)
完成后,服务器会加载login.php,确定这是新用户还是现有用户,然后分别加载新用户表单或主页:
session_start();
if (!$_SESSION['auth']) {
print(" You must be signed in to edit your profile.");
} else {
if ($_SESSION['userId']) { // If userId is set, existing user
header('Location: index.php');
} else { // userId is not set, new user
header('Location: profileedit.php');
}
}
还有什么我可以看的建议吗?该解决方案在我的本地机器上运行良好,只是在我上传和托管时效果不佳。
下面的cmets,
session_id() 在我的本地机器上从 index.php 到 login.php 到 oauth.php 到 profile.php 是一致的。但是,当我浏览托管服务器上的 error_log 时,我看到以下错误消息:
[Sun Oct 17 17:24:32.094053 2021] [php7:error] [pid 25817] [client XXX:51629] PHP Fatal error: Uncaught Firebase\\JWT\\BeforeValidException: Cannot handle token
prior to 2021-10-17T17:24:54+0000 in /var/www/html/vendor/firebase/php-jwt/src/JWT.php:142\nStack trace:\n#0 /var/www/html/vendor/google/apiclient/src/AccessToken/Verify.php
(106): Firebase\\JWT\\JWT::decode()\n#1 /var/www/html/vendor/google/apiclient/src/Client.php(793): Google\\AccessToken\\Verify->verifyIdToken()\n#2 /var/www/html/includes/oa
uth.php(18): Google\\Client->verifyIdToken()\n#3 {main}\n thrown in /var/www/html/vendor/firebase/php-jwt/src/JWT.php on line 142, referer: http://XXX/login.
php
在 17:24:32 记录了错误,并且令牌似乎设置为从 17:24:54 开始有效。难道仅仅是因为谷歌的身份验证服务器和托管的网络服务器(顺便说一下,谷歌云)之间存在时间同步问题吗? 我还在 error_log 中注意到 $_SESSION['auth'] 是“未定义的索引”,这表明身份验证根本没有发生 - 尽管经过几次刷新后,身份验证才会起作用,这可能支持时间同步问题。不过不太确定我能做些什么!
进一步更新。 看起来问题是由于时间差异造成的。其实在google API库vendor/firebase/php-jwt/src/JWT.php中有如下注释和代码:
/**
* When checking nbf, iat or expiration times,
* we want to provide some extra leeway time to
* account for clock skew.
*/
public static $leeway = 1;
我试图在我的代码中使用:
$jwt = new \Firebase\JWT\JWT; //Allow for discrepancies between server and auth times
$jwt::$leeway = 5;
但这没有用。于是我直接编辑了 vendor/firebase/php-jwt/src/JWT.php 中的代码:
/**
* When checking nbf, iat or expiration times,
* we want to provide some extra leeway time to
* account for clock skew.
*/
public static $leeway = 5;
我还编辑了 vendor/google/apiclient/src/AccessToken/Verify.php 如下:
// if (property_exists($jwtClass, 'leeway') && $jwtClass::$leeway < 1) { // Original code. Remove the $leeway<1 constraint as the $leeway would not be < 1
if (property_exists($jwtClass, 'leeway')) {
// Ensures JWT leeway is at least 1
// @see https://github.com/google/google-api-php-client/issues/827
$jwtClass::$leeway = 5;
}
但这仍然不起作用。我还是被难住了!
【问题讨论】:
-
从登录到未登录错误的具体路径是什么?例如,它是否从登录重定向到个人资料编辑页面?如果出现错误并随后登录状态发生变化,这是新用户还是现有用户?
-
请通过
session_id();验证您的页面请求之间的会话ID 相同。如果会话 ID 在您的页面请求之间发生变化,您将获得新的(空)会话。 -
谢谢两位。我在上面的问题中添加了更多内容。
-
您尝试过什么来解决问题?你被困在哪里了? “可能仅仅是因为 Google 的身份验证服务器和托管的网络服务器之间存在时间同步问题” - 是的,这听起来很有效
-
请不要在供应商文件夹中编辑代码。下次您使用 Composer 安装或更新软件包时,此类更改将被删除
标签: php session-variables google-signin