如何在 PHP 中为 $_SESSION 组成一个唯一的名称?
Posted
技术标签:
【中文标题】如何在 PHP 中为 $_SESSION 组成一个唯一的名称?【英文标题】:How to make up a unique name for a $_SESSION in PHP? 【发布时间】:2012-05-11 12:30:45 【问题描述】:作为我正在创建的登录系统的一部分,我会在以每个客户端命名的唯一会话中跟踪失败的登录尝试:
if($login_failed)
// update failed login attempts
$session_name = 'failed_attempts'.$_SERVER['REMOTE_ADDR'];
if(!isset($_SESSION[$session_name]))
$_SESSION[$session_name] = 1;
else
$_SESSION[$session_name] += 1;
如您所见,为了确定每个会话的唯一名称,我将用户的 IP 地址附加到字符串“failed_login_attempts”的末尾。
如果用户尝试失败 5 次,我需要在每次后续尝试时填写验证码。
我只是担心在某些网络中可能会为许多用户分配相同的 IP 地址,在这种情况下,如果 1 个用户无法登录,他们都会开始看到验证码,即使只需要显示 1 个用户验证码。
这是合理的还是从来没有两个用户可以拥有相同 IP 的情况,例如他们可能有相同的前 3 个八位字节,但最后一个数字会不同,在这种情况下我不必担心。
如果有可能多个用户共享同一个 IP,那么确定会话名称的唯一标识符以将未登录用户链接到会话的好方法是什么?
【问题讨论】:
【参考方案1】:会话已经是唯一的,因为它与特定浏览器上特定用户的 cookie 相关联。您无需担心它会泄露给其他用户。
session id 将这一切联系在一起。
幕后实际发生的事情是 php 在浏览器上存储了一个带有唯一 ID(会话 ID)的 cookie,该 ID 与存储在服务器上的数据结构相关联。除了那个 id 之外,没有任何实际的会话数据离开服务器。它实际上是一个文件,如果你在你的 php 文件夹中四处寻找,你可以看到它。
【讨论】:
对,但是我应该在问号的位置放什么来实际查看是否已经进行了至少 5 次失败的尝试--------> if(isset($_SESSION[?? ?]) && $_SESSION[???] == '5') 换句话说,我如何将失败的会话与用户关联起来,因为用户尚未登录。 将尝试次数存储在变量中,如果大于 5,请按照您的逻辑进行操作。真的就是这么简单。但是,由于它是基于 cookie 的,您可能希望在数据库中为该用户存储某种警报。 正如 michael 在下面指出的,如果用户清除了他们的 cookie,他们可以再试一次,这就是我提到在某处存储警报的原因。 将失败的尝试存储在数据库中会导致同样的问题。因为即使那样我也需要将失败的尝试与特定用户相关联。这就是为什么我试图在会话名称中使用 IP。仍然需要一种方法将失败的尝试与特定用户唯一关联。【参考方案2】:在大多数学校、家庭和办公室网络中,您的用户将共享 IP 地址,因为他们将从 NAT 内部或通过出站防火墙访问更广泛的 Internet。使用uniqid()
生成与每个故障相关联的唯一值。不过这并不是完全必要的,因为session_id()
已经为每个用户会话保存了一个唯一值。
要跟踪会话中的故障,您真正需要做的就是在该会话中增加一个变量。
if (failed_login)
$_SESSION['failed_logins']++;
$threshold = 5;
if ($_SESSION['failed_logins'] >= $threshold)
// Do whatever is needed when too many failures occur
但是请注意,这不能阻止用户简单地重新启动浏览器以获取新会话。您可以添加更多的箍来跳过,例如还记录用户代理,但这也可能导致同一网络上的其他用户的潜在冲突,并且仍然可以被聪明的最终用户欺骗或更改以绕过您的限制。
【讨论】:
【参考方案3】:更好的解决方案是标记/增加用户表中的一列,当它达到 5 时,触发验证码。成功登录后,将值重置为 0。
【讨论】:
我不同意。这似乎是有价值的建议,而且这个问题并没有真正允许答案中包含太多代码。我想要一些关于如何从数据库触发器触发验证码的详细信息......以上是关于如何在 PHP 中为 $_SESSION 组成一个唯一的名称?的主要内容,如果未能解决你的问题,请参考以下文章