【问题标题】:What is the best way to secure an application with session vars?使用会话变量保护应用程序的最佳方法是什么?
【发布时间】:2015-08-01 07:00:44
【问题描述】:

我有一个带有索引页面的应用程序,用户可以在其中输入登录名和密码。然后将它们作为 POST 变量提交,如果它们都正确,我的脚本会创建一个会话变量,如下所示:

$_SESSION['auth'] = $login;

并且索引页面会回显一个菜单。如果不是,则再次显示登录窗口,就像用户第一次进入索引页面一样(在必填字段下显示错误消息)。

现在,我验证会话变量是否已设置:

<?php
include 'functions.php'; //this file contains session_start() 
if (!isset($_SESSION['auth'])) {
        header("Location: index.php");
        exit();
    }
?>
<html>
Html stuff with jquery...
</html>

我是否必须将我所有的 html 内容放在 else 语句中的括号中,或者我的页面足够安全?即使用户被重定向,html部分仍然是由他的浏览器获取的,不是吗?

我的服务器上有几个 PHP 页面,在每个页面的开头我都进行与上述相同的测试。当用户进入索引页面时,我也会进行此验证(如果他已经登录,我不希望他再次登录)。

假设我的脚本是安全的(用户提供的所有信息都在服务器端进行检查),使用安全会话的最佳方式是什么?

【问题讨论】:

标签: php security session


【解决方案1】:

很高兴您考虑到安全性,但请允许我稍微解释一下会话和会话 cookie 的工作原理。

首先,cookie 只允许在其中存储有限数量的数据,我忘记了多少,但我知道它不是无限的。那么服务器如何允许您存储所有会话数据。实际的会话 cookie 仅存储会话 ID。在服务器上有一个实际的物理文件,其中包含会话数据。因此,当客户端连接时,它们会发送会话 id,这反过来会告诉要使用什么文件。因此,会话与服务器文件系统和用于创建 cookie id 的算法一样安全。没有实际的会话数据(除了那个 id )离开服务器。

也就是说,有 2 种设置可能有助于确保会话安全。

这些是 httponly 且安全的,您可以在此处阅读有关它们的更多信息

http://php.net/manual/en/session.configuration.php#ini.session.cookie-httponly

现在简而言之,安全意味着仅通过 Https 传输会话数据(会话 ID),这仅在您的服务器和网站上设置了 https 时才有效。 Httponly,告诉浏览器 cookie 只能通过 http(或 https)而不是客户端脚本发送。但是,由于您无法控制客户端使用的浏览器,或者他们的计算机是否以某种方式受到损害,否则会告诉浏览器(尽管我不知道任何可能这样做的漏洞利用),您真的只是在做一个给客户端机器的建议。

现在就实际数据的安全性而言,任何来自任何地方的输入,甚至是您自己的数据库,都应始终被视为潜在的不安全。这并不意味着你必须到处检查它,主要是你在输出到页面时对html进行了转义,并且你使用了适当的手段来防止sql注入数据库。作为一般规则,这些应在入口处完成。

例如,当将内容输出到不应包含 html 的页面时,只需在输出时使用 html_entities 等。在 sql 中使用数据时,请在此处使用准备好的语句。您看到您不需要每次触摸 $_POST 数据时都检查它,只需在使用它之前检查数据以防可能被利用的东西,例如将其保存在数据库中。

让我们举一个小例子函数(假设它在一个用户类中)

 public function getUser( $id ){
      $sql = "Select * from user where id = $id"
       //execute sql
 }

我们永远不会使用 PDO 执行此操作,但假设这是老派的东西,您从其他地方的登录表单中过滤数据,所以当您设置它时,您假设它始终是一个干净的 id,因为您在登录表格。然后,您需要会话中的用户。好吧,你也有 id,所以你使用它。现在是来自会话清洁的 id,谁知道是对的。也许它是来自文件的 id,或者其他一些不起眼的地方。谁知道 Id 来自哪里(当我们创建用户类时)。因此,我们现在所做的就是检查或使用准备好的语句“在我们使用的点”数据,即入口点。然后我们不在乎数据来自哪里。因为,它总是在准备好的语句中被清除,就在我们在数据库中使用它之前。这样一来,它总是 100%,没有问题,干净。我们可以在运行查询的地方看到它。如果我们稍后制作新的登录表单,我们不必担心。也许您在某处添加了一个弹出式登录表单?没关系,你的 sql 永远是干净的。现在,我并不是说不要在登录表单中检查它。确保安全永远不会受到伤害,更不用说您可能想要验证其他内容,电子邮件格式,用户名的唯一性等。但是,关键点已经涵盖。

有意义吗?

为了解决您关于不使用 cookie 的评论(我应该在开始时对此进行解释)。就其本质而言,互联网是无国籍的。这意味着每次页面重新加载本质上都是一个新的连接。维护登录(或跨重新加载的任何数据)的唯一方法是在请求之间传递一些数据。通常只有几种方法可以做到这一点,它们是 $_POST$_GET$_FILE$_COOKIES。注意它们的格式,这是一个提示,它们被称为超级全局变量。

http://php.net/manual/en/language.variables.superglobals.php

顺便说一句,我们要感谢 Netscape 的 Cookie 和 Javascript,这两者都是 IE “借来的”,对我来说很遗憾我再也看不到 Netscape Navigator。我记得从 AOL 3.0 时代开始,那是在您可以在电子邮件中嵌入图像之前。你们这些老前辈知道我在说什么……Churr.Beep.bong.Cherrrk(各种模拟调制解调器噪音)……流媒体视频那是什么,下载一首歌需要 1.5 天。 & Pr@y 2 teh GodZ of de inTerWeBz MomZ do4't g3t a [ call .... L33t BaBy >:-)~ ^v^

【讨论】:

  • 谢谢,但我现在不使用 cookie,只使用会话变量。但你是对的,最好也为他们提供一个使用 https 保护的登录过程。也许我的问题不够清楚,我会尝试编辑它,谢谢
  • 您认为该会话是如何维护的?在会话 cookie 中。我们将做一个小实验,现在登录到您不使用 cookie 的网站。按 ctrl+shift+del,清除历史记录。确保选中活动登录。清除浏览器的“cookies”。现在看看您是否已登录。
  • 哇,你添加了很多东西,谢谢你的回答!
  • 当然,这是我们所说的互联网的基础。一旦你理解了一个请求是无状态的,这一切都是有意义的,承诺。
  • 记住我,你想要的是我喜欢称之为护照的东西。制作另一个单独的 cookie,将哈希码放入其中,并制作一个单独的护照表,以进行比较。这样您就不会暴露用户密码,您可以在表中设置生命周期,并清除过期的旧护照。同一张表可用于通过使用护照代码创建登录链接来重置用户密码,即只能使用一次。要制作护照,您可以执行sha1( microtime().$userid.rand(0,10000));,这将给出一个 40 个字符的字符串,由于时间的不同,该字符串总是不同的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-29
  • 2019-09-23
  • 1970-01-01
  • 2011-10-13
  • 2012-08-30
  • 2020-09-26
  • 1970-01-01
相关资源
最近更新 更多