Cookie学习笔记(三)

11.4.3  删除会话变量

在使用会话时,需要创建一个方法来删除会话数据。在当前示例中,当用户注销时,这是必要的。

虽然cookie系统只需要发送另一个cookie来销毁现有的cookie,但是会话的要求更高,因为既要考虑客户上的cookie,又要考虑服务器上的数据。

要删除单独一个会话变量,可以使用unset()函数(它可以处理PHP中的任何变量):

unset($_SESSION['var']);

要删除每个会话变量,可以重置整个$_SESSION数组:

$_SESSION = array();

最后,要从服务器中删除所有的会话数据,可使用session_destroy():

session_destroy();

注意,在使用其中的任何一个方法之前,页面都必须开始于session_start(),使得会访问现有的会话。让我们更新logout.php脚本,以清理会话数据。

删除会话

(1) 在文本编辑器或IDE中打开logout.php(参见脚本11-6)。

(2) 紧接在开始PHP行之后启动会话(参见脚本11-11)。

session_start();

脚本11-11  销毁会话(就像在注销页面中所做的那样)需要使用特殊的语法,以删除服务器上的会话cookie和会话数据,以及清理$_SESSION数组

1 <?php # Script 11.11 - logout.php #2

2 // This page lets the user logout.

3

4 session_start(); // Access the existing session.

5

6 // If no session variable exists, redirect the user:

7 if (!isset($_SESSION['user_id'])) {

8

9   require_once ('includes/login_functions.inc.php');

10    $url = absolute_url();

11    header("Location: $url");

12    exit();

13 

14  } else { // Cancel the session.

15 

16    $_SESSION = array(); // Clear the variables.

17    session_destroy(); // Destroy the session itself.

18    setcookie ('PHPSESSID', '', time()-3600, '/', '', 0, 0); // Destroy the cookie.

19 

20  }

21 

22  // Set the page title and include the HTML header:

23  $page_title = 'Logged Out!';

24  include ('includes/header.html');

25 

26  // Print a customized message:

27       echo "<h1>Logged Out!</h1>

28       <p>You are now logged out!</p>";

29 

30  include ('includes/footer.html');

31  ?>

无论何时使用会话,都必须使用session_start()函数,最好是在页面顶部这样做,即使删除会话也是如此。

(3) 更改条件语句,使得它检查会话变量是否存在。

if (!isset($_SESSION['user_id'])) {

与cookie示例中的logout.php脚本一样,如果用户目前没有登录,就会重定向他们。

(4) 用下面的几行代码替换setcookie()行(它删除cookie):

$_SESSION = array();

session_destroy();

setcookie ('PHPSESSID', '', time()-3600, '/', '', 0, 0);

这里的第一行代码将把整个$_SESSION变量重置为一个新数组,从而清除其现有的值。第二行代码从服务器中删除数据,第三行代码则会发送一个cookie,用以替换浏览器中现有的会话cookie。

(5) 删除消息中对$_COOKIE的引用。

echo "<h1>Logged Out!</h1>

<p>You are now logged out!</p>";

与使用logout.php脚本的cookie版本时不同,不能再通过用户的名字来引用他们,因为所有这类数据都已被删除。

(6) 将文件另存为logout.php,存放在Web目录中,并在浏览器中测试它(参见图11-19)。

 

图11-19  注销页面(现在具有会话)

ü提示

l    永远不要把$_SESSION设置成等于NULL并且永远不要使用unset($_SESSION),因为它们都可能会在某些服务器上引发问题。

l    以免你对接下来将要发生的事情不是绝对清楚,提供了关于会话的三类信息:会话标识符(它默认存储在cookie中)、会话数据(它存储在服务器上的一个文 本文件中)和$_SESSION数组(它指定了脚本访问文本文件中的会话数据的方式)。仅仅删除cookie不会删除文本文件,反之亦然。清 理$_SESSION数组将会清除文本文件中的数据,但是文件本身将仍然存在,cookie也是如此。这个注销脚本中概括的三个步骤实际上会删除会话的所 有痕迹。

更改会话行为

作为PHP对会话所提供支持的一部分,可以为PHP处理会话的方式设置大约20种不同的配置选项。有关完整列表,参见PHP手册,但是我将在这里重点介绍几个最重要的选项。注意关于更改会话设置的两条规则:

(1) 所有更改都必须在调用session_start()之前完成。

(2) 必须在使用会话的每个页面执行相同的更改。

(3) 可以在PHP脚本内使用ini_set()函数(在第7章中讨论过)设置大多数选项:

ini_set(parameter, new_setting);

例如,如果需要使用会话cookie(如前所述,在不使用cookie的情况下会话也可以工作,但是这样不太安全),则可使用:

ini_set ('session.use_only_cookies', 1);

还可以更改会话的名称(也许是为了使用一个更为用户友好的名称),这时可以使用session_name()函数。

session_name('YourSession');

创建自己的会话名称有双重好处:它更安全一点,并且可以更好地被最终用户接收(因为会话名称是最终用户将使用的cookie名称)。在删除会话cookie时,也可以使用session_name()函数:

setcookie (session_name(), '', time()-3600);

最后,还有一个session_set_cookie_params()函数。它用于调整会话cookie的设置。

session_set_cookie_params(expire, path, host, secure, httponly);

注意:cookie的到期时间只指cookie在Web浏览器中的寿命,而不是指会话数据将在服务器上存储多长时间。

 

11.5  提高会话安全性

由 于重要的信息通常存储在会话中(永远都不应该把敏感数据存储在cookie中),所以安全性变得更重要。关于会话需要注意以下两项:会话ID和会话数据本 身,前者是一个指向会话数据的引用,后者存储在服务器上。一个不怀好意的人极有可能通过会话ID(而不是通过服务器上的数据)来入侵一个会话,因此,在这 里将重点关注这方面的事情(在本节末尾的“提示”中,我提到了保护会话数据的两种方式)。

会话ID是会话数据的关键。默认情况下,PHP 将 其存储在cookie中,从安全的角度讲,这是首选的方法。在PHP中可以在不使用cookie的情况下使用会话,但是这会使应用程序遭受会话劫持 (session hijacking):如果我可以获悉另一个用户的会话ID,就可以轻松地欺骗服务器把它看作是我的会话ID。此时,我就有效地接管了原用户的整个会话, 并且可以访问他们的数据。因此,把会话ID存储在cookie中使得它更难被窃取。

防止劫持的一种方法是:在会话中存储某种用户标识符, 然 后反复地复查这个值。HTTP_USER_AGENT(所用的浏览器和操作系统的组合)是针对此目的的一个可能的候选。这会增加一层安全性,因为仅当我运 行的浏览器和操作系统与另一位用户的完全一样时,才能够劫持他的会话。为了演示这一点,让我们最后一次修改示例。

防止会话固定

另 一种特定的会话攻击被称为会话固定(session fixation)。其中,一位不怀好意的用户指定了另一位用户应该使用的会话ID。这个会话ID可以是随机生成的,或者是合法创建的。在这两种情况下, 真实的用户都会使用固定的会话ID进入站点,并做任何事情。然后,那位不怀好意的用户可以访问那个会话,因为他们知道会话ID是什么。你可以在用户登录后 通过更改会话ID来帮助防止这些类型的攻击。session_regenerate_id()正是用于执行该任务的,它提供一个新的会话ID来引用当前的 会话数据。如果站点的安全性极为重要(如电子商务或在线银行业务),或者如果用户的会话被操纵情况就变得特别糟糕时,就可以使用这个函数。

更安全地使用会话

(1) 在文本编辑器或IDE中打开login.php(参见脚本11-8)。

(2) 在给其他会话变量赋值之后,还存储HTTP_USER_AGENT值(参见脚本11-12)。

$_SESSION['agent'] = md5($_SERVER ['HTTP_USER_AGENT']);

脚本11-12  login.php脚本的这个最终版本也在会话中存储了用户的HTTP_USER_AGENT(客户的浏览器和操作系统)的加密形式

1 <?php # Script 11.12 - login.php #4

2

3 if (isset($_POST['submitted'])) {

4

5   require_once ('includes/login_functions.inc.php');

6   require_once ('../mysqli_connect.php');

7   list ($check, $data) = check_login($dbc, $_POST['email'], $_POST['pass']);

8

9   if ($check) { // OK!

10 

11      // Set the session data:.

12      session_start();

13      $_SESSION['user_id'] = $data['user_id'];

14      $_SESSION['first_name'] = $data['first_name'];

15 

16      // Store the HTTP_USER_AGENT:

17      $_SESSION['agent'] = md5($_SERVER['HTTP_USER_AGENT']);

18 

19      // Redirect:

20      $url = absolute_url ('loggedin.php');

21      header("Location: $url");

22      exit();

23 

24    } else { // Unsuccessful!

25      $errors = $data;

26    }

27 

28    mysqli_close($dbc);

29 

30  } // End of the main submit conditional.

31 

32  include ('includes/login_page.inc.php');

33  ?>

HTTP_USER_AGENT是$_SERVER数组的一部分(你可以返回到第1章,回忆一下使用它的方式)。它将具有一个像Mozilla/4.0这样的值(与之兼容的值、MSIE 6.0、Windows NT 5.0、.NET CLR 1.1.4322)。

为了提高安全性,这里没有把这个值存储在会话中,而是用md5()函数处理它。该函数基于一个值返回32个字符的十六进制字符串[称为散列(hash)]。理论上讲,任何两个字符串都不具有相同的md5()结果。

(3) 保存文件,存放在Web目录中。

(4) 在文本编辑器或IDE中打开loggedin.php(参见脚本11-9)。

(5) 将!isset($_SESSION['user_id'])条件语句更改如下(参见脚本11-13):

if(!isset($_SESSION['agent']) OR ($_SESSION ['agent'] != md5      ($_SERVER['HTTP_USER_AGENT']))){

脚本11-13  这个loggedin.php脚本现在确认访问这个页面的用户具有与他们登录时相同的HTTP_ USER_ AGENT

1 <?php # Script 11.13 - loggedin.php #3

2

3 // The user is redirected here from login.php.

4

5 session_start(); // Start the session.

6

7 // If no session value is present, redirect the user:

8 // Also validate the HTTP_USER_AGENT!

9 if (!isset($_SESSION['agent']) OR ($_SESSION['agent'] != md5($_SERVER['HTTP_USER_AGENT']) ) ){

10    require_once ('includes/login_functions.inc.php');

11    $url = absolute_url();

12    header("Location: $url");

13    exit();

14  }

15 

16  $page_title = 'Logged In!';

17  include ('includes/header.html');

18 

19  // Print a customized message;

20  echo "<h1>Logged In!</h1>

21  <p>You are now logged in, {$_SESSION['first_name']}!</p>

22  <p><a href=\"logout.php\">Logout</a></p>";

23 

24  include ('includes/footer.html');

25  ?>

这 个条件语句用于检查两件事情。首先,它会查看$_SESSION['agent']变量是否未设置(这一部分就像它以前一样,尽管使用的是agent而不 是user_id)。这个条件语句的第二部分用于检查$_SERVER['HTTP_ USER_AGENT']的md5()版本是否不等于$_SESSION ['agent']中存储的值。如果这两个条件中有一个为真,就会重定向用户。

(6) 保存这个文件,存放在Web目录中,并通过登录在Web浏览器中测试它。

ü提示

l    对于至关重要的会话应用,只要有可能,就需要使用cookie并通过安全连接传输它们。你甚至可以通过把session.use_only_cookies设置成1(在PHP 6中,这是默认设置),将PHP设置成只使用cookie。

l    如果你使用与其他域共享的服务器,那么把session.save_path从其默认设置(可以被所有用户访问)更改成稍微更本地化一些将会更安全。

l    会话数据本身可以存储在数据库中,而不是文本文件中。这样更安全,但这是一个编程密集的选项。我在PHP 5 Advanced: Visual QuickPro Guide一书中讲述了如何执行该任务。

l    用户的IP地址(用户通过其建立连接的网络地址)不是一个良好的唯一标识符,这有两个原因。首先,用户的IP地址可能(并且通常会)频繁地发生变化 (ISP在短时间内动态地分配它们)。其次,从同一个网络(如家庭网络或办公室)访问一个站点的许多用户可能都具有相同的IP地址。

转载于:https://www.cnblogs.com/maomiyy/p/3762197.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值