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地址。

Cookie学习笔记(三),布布扣,bubuko.com

时间: 2024-10-12 15:51:35

Cookie学习笔记(三)的相关文章

Cookie学习笔记(一)

Cookie 简介 一.简介     说起来,Cookie应该是一种应用较久的技术了.早在HTML刚刚出现的时候,在每个独立的页面之间没有办法记录和 标识不同的用户.后来人们就发明了Cookie技术,当用户访问网页时,它能够在访问者的机器上创立一个文件,我们把它叫作Cookie,写一段内容进去,来标识不同的用户.如果下次用户再访问这个网页的时候,它又能够读出这个文件里面的内容,这样网页就知道上次这个用户已经访问过该网页了.      虽然现在网页的制作技术比起几年以前已经发展了许多.不过有些时候

【Unity 3D】学习笔记三十二:游戏元素——游戏光源

游戏光源 在3D游戏中,光源是一个非常具有特色的游戏组件.用来提升游戏画面质感的.如果没有加入光源,游戏场景可能就会显得很昏暗.在unity中提供了三种不同的光源类型:点光源,聚光灯,平行光. 点光源 顾名思义,点光源是从一个点向周围散发出光的光源,就像电灯一样.创建点光源在hierarchy视图中点击create--point light: 创建完以后,点击点光源对象,在右侧inspector视图中可以看到点光源的所有信息: type:光源的类型.有point(点光源),directional

Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle&lt;T&gt;

Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T> 今天 说一下Caliburn.Micro的IEventAggregator和IHandle<T>分成两篇去讲这一篇写一个简单的例子 看一它的的实现和源码 下一篇用它们做一个多语言的demo 这两个是事件的订阅和广播,很强大,但用的时候要小心发生不必要的冲突. 先看一下它的实现思想 在Caliburn.Micro里EventAggregator要以单例的形式出现这样可以

OpenCV for Python 学习笔记 三

给源图像增加边界 cv2.copyMakeBorder(src,top, bottom, left, right ,borderType,value) src:源图像 top,bottem,left,right: 分别表示四个方向上边界的长度 borderType: 边界的类型 有以下几种: BORDER_REFLICATE # 直接用边界的颜色填充, aaaaaa | abcdefg | gggg BORDER_REFLECT # 倒映,abcdefg | gfedcbamn | nmabcd

NFC学习笔记——三(在windows操作系统上安装libnfc)

本篇翻译文章: 这篇文章主要是说明如何在windows操作系统上安装.配置和使用libnfc. 一.基本信息 1.操作系统: Windows Vista Home Premium SP 2 2.硬件信息: System: Dell Inspiron 1720 Processor: Intel Core 2 Duo CPU T9300 @ 2.5GHz 2.5GHz System type: 32-bit Operating System 3.所需软件: 在windows操作系统上安装软件需要下列

swift学习笔记(三)关于拷贝和引用

在swift提供的基本数据类型中,包括Int ,Float,Double,String,Enumeration,Structure,Dictionary都属于值拷贝类型. 闭包和函数同属引用类型 捕获则为拷贝.捕获即定义这些常量和变量的原作用域已不存在,闭包仍然可以在闭包函数体内引用和修改这些值 class属于引用类型. Array的情况稍微复杂一些,下面主要对集合类型进行分析: 一.关于Dictionary:无论何时将一个字典实例赋给一个常量,或者传递给一个函数方法时,在赋值或调用发生时,都会

加壳学习笔记(三)-简单的脱壳思路&amp;调试思路

首先一些windows的常用API: GetWindowTextA:以ASCII的形式的输入框 GetWindowTextW:以Unicaode宽字符的输入框 GetDlgItemTextA:以ASCII的形式的输入框 GetDlgItemTextW:以Unicaode宽字符的输入框 这些函数在使用的时候会有些参数提前入栈,如这函数要求的参数是字符串数目.还有大小写啦之类的东西,这些东西是要在调用该函数之前入栈,也就是依次push,就是说一般前面几个push接着一个call,那前面的push可能

【Unity 3D】学习笔记三十四:游戏元素——常用编辑器组件

常用编辑器组件 unity的特色之一就是编辑器可视化,很多常用的功能都可以在编辑器中完成.常用的编辑器可分为两种:原有组件和拓展组件.原有组件是编辑器原生的一些功能,拓展组件是编辑器智商通过脚本拓展的新功能. 摄像机 摄像机是unity最为核心组件之一,游戏界面中显示的一切内容都得需要摄像机来照射才能显示.摄像机组件的参数如下: clear flags:背景显示内容,默认的是skybox.前提是必须在render settings 中设置天空盒子材质. background:背景显示颜色,如果没

马哥学习笔记三十二——计算机及操作系统原理

缓存方式: 直接映射 N路关联 缓存策略: write through:通写 write back:回写 进程类别: 交互式进程(IO密集型) 批处理进程(CPU密集型) 实时进程(Real-time) CPU: 时间片长,优先级低IO:时间片短,优先级高 Linux优先级:priority 实时优先级: 1-99,数字越小,优先级越低 静态优先级:100-139,数据越小,优先级越高 实时优先级比静态优先级高 nice值:调整静态优先级   -20,19:100,139   0:120 ps