Zend framework——会话

简介
Zend_Session 用来在由相同客户端发起的多个页面请求之间,管理和保护会话数据 。 会话命名空间(Session Namespaces) 提供了使用经典的命名空间 方式来访问会话数据,命名空间逻辑上就是一系列被命名(键名为字符串)的联合数组(类似于普通的 PHP 数组)。

基本用法
在Zend Framework中,Zend_Session_Namespace实例提供了操作会话数据主要的API。命名空间常用于隔离所有的会话数据,尽管也为所有会话数据只需要一个命名空间的情况提供了一个默认的命名空间。Zend_Session利用了PHP内置的会话模块(ext/session),以及它特有的$_SESSION全局数组做为会话状态数据的存储机制。虽然$_SESSION在PHP的全局命名空间内仍然可以访问,但是开发者不应该直接访问它,这样Zend_Session 和 Zend_Session_Namespace可以提供一组最可靠、安全的处理会话相关的功能。

每个Zend_Session_Namespace的实例对应于$_SESSION全局数组的一个条目,在那里命名空间被用作键。

<?php
require_once 'Zend/Session/Namespace.php';

$myNamespace = new Zend_Session_Namespace('myNamespace');

// $myNamespace corresponds to $_SESSION['myNamespace']

用Zend_Session直接和其它使用 $_SESSION的代码协同工作是可能的。然而,为避免问题,强烈建议这样的代码只使用$_SESSION中不和Zend_Session_Namespace的实例相对应的部分。

命名空间
在初始化Zend_Session时,如果没有指定命名空间,所有的数据将被透明地储存在’Default’命名空间下。Zend_Session不打算直接处理会话命名空间容器的内容,而是使用Zend_Session_Namespace。下面的例子演示了默认命名空间的使用,和怎样计算用户访问页面的次数:

例 页面浏览计数

<?php
require_once 'Zend/Session/Namespace.php';

$defaultNamespace = new Zend_Session_Namespace('Default');

if (isset($defaultNamespace->numberOfPageRequests)) {
    $defaultNamespace->numberOfPageRequests++; // 每次页面加载,这个将递增
} else {
    $defaultNamespace->numberOfPageRequests = 1; // 第一次
}

echo "Page requests this session: ", $defaultNamespace->numberOfPageRequests;

当多个模块使用Zend_Session_Namespace的实例拥有不同的命名空间,每个模块为它自己的会话数据获得数据封装。可以传递给Zend_Session_Namespace构造函数一个可选的$namespace参数,它允许开发者分割会话数据到分离的命名空间。

命名空间的名称被限定为字符序列,它表示为不以下划线(“_”)开头的非空PHP字符串。只有Zend Framework的核心模块可使用以”Zend”开头的命名空间的名称。

新方法: 使用命名空间避免冲突

<?php
require_once 'Zend/Session/Namespace.php';

// in the Zend_Auth component
$authNamespace = new Zend_Session_Namespace('Zend_Auth');
$authNamespace->user = "myusername";

// in a web services component
$webServiceNamespace = new Zend_Session_Namespace('Some_Web_Service');
$webServiceNamespace->user = "myrootname";

上述例子中的代码与下面的代码有相同的效果,不过,上述例子中的会话对象把会话数据封装进了各自的命名空间。

老方法: PHP会话访问

<?php
$_SESSION['Zend_Auth']['user'] = "myusername";
$_SESSION['Some_Web_Service']['user'] = "myrootname";

循环会话命名空间
Zend_Session_Namespace提供了IteratorAggregate接口所有的功能,包括对foreach语句的支持:

<?php
require_once 'Zend/Session/Namespace.php';

$aNamespace = new Zend_Session_Namespace('some_namespace_with_data_present');

foreach ($aNamespace as $index => $value) {
    echo "aNamespace->$index = '$value';\n";
}

访问会话数据
Zend_Session_Namespace实现_get(), _set(), _isset(), and _unset()这些 魔术方法,除非在一个子类里,否则这些魔术方法不能被直接调用。但是正常的操作符自动调用这些方法,如下例所示:

<?php
require_once 'Zend/Session/Namespace.php';

$namespace = new Zend_Session_Namespace(); // 默认的命名空间

$namespace->foo = 100;

echo "\$namespace->foo = $namespace->foo\n";

if (!isset($namespace->bar)) {
    echo "\$namespace->bar not set\n";
}

unset($namespace->foo);

39.3. 高级用法
1.开启会话
如何你希望所有的请求都有个由Zend_Seesion管理的会话,那么请在程序的引导文件中开启它:

例 开启全局会话

<?php
require_once 'Zend/Session.php';

Zend_Session::start();

在程序的引导文件中开启会话,可以避免会话开启之前HTTP响应头返回用户浏览器,那样可能会破坏web页面的美观。许多高级的特性需要先执行Zend_Session::start()。

使用Zend_Session组件,有4种开启会话的方法,其中2种是错误的。

错误方式1:不要开启PHP的session.auto_startsetting。如果你使用mode_php并在php.ini中已经开启了该选项,而你又没有权限去关闭该选项,你可以在.htaccess文件(这个文件通常在HTML文档根目录下)中增加下面这一句:

php_value session.auto_start 0

错误方式2:不要直接使用PHP的session_start()函数。如果你直接使用session_start(),之后再使用Zend_Session_Namespace,那么Zend_Session::start()会抛出(”会话已经开始”)的异常。如果你在使用Zend_Session_Namespace或使用Zend_Session::start()后调用session_start(),那么会产生一个E_NOTICE级别的错误,且该调用将会被忽略。

正确方式1:使用Zend_Session::start()开启会话。如果你想让每个页面请求都开启会话,那么应该在ZF应用程序的引导文件(index.php)中尽早的调用这个函数。开启会话有些额外的开销,如果只有部分页面请求需要开启会话,那么就:

在引导文件中,使用Zend_Session::setOptions()无条件地设置strict选项为true,strict 选项防止 new Zend_Session_Namespace() 自动调用 Zend_Session::start()。

在任何Zend_Session_Namespace()对象初始化之前只对需要使用会话的请求调用Zend_Session::start()。

象往常一样,在需要会话的地方,使用new Zend_Session_Namespace(),但必须确认先前已经调用过Zend_Session::start()了。

正确方式2:只要有需要使用会话的地方,就初始化new Zend_Session_Namespace(),并且基本的PHP会话将自动开启。这个极端简单的用法能在大多数的情形下很好地工作。然而,如果你使用地是默认的基于cookie的会话(强烈推荐使用这种方式),你必须确保在第一次调用new Zend_Session_Namespace()在任何PHP发向向客户端输出(例如,HTTP headers)之前。

2.锁住会话命名空间
会话的命名空间可以加锁,以防止意外的移除该命名空间下的会话变量值。使用lock()方法使某命名空间下会话变量变为只读,unlock()方法使一个只读的命名空间变为可读写,isLocked()方法测试某命名空间是否已经被加锁。加锁是短暂的,且只在此页面请求内有效,不会持续到下一个页面请求。给命名空间加锁不会影响到存储在该命名空间下对象的setter方法,但是阻止了命名空间的setter方法的移除或替换对象。也就是说,虽给Zend_Session_Namespace的实例加了锁,但还是不能阻止它处同样引用了命名空间下数据的对它的变更。

<?php
require_once 'Zend/Session/Namespace.php';

$userProfileNamespace = new Zend_Session_Namespace('userProfileNamespace');

// 标记会话设置为只读锁定
$userProfileNamespace->lock();

// 解锁只读锁定
if ($userProfileNamespace->isLocked()) {
$userProfileNamespace->unLock();
}

3.命名空间过期
对于命名空间和在命名空间中的独立键,它们的寿命都是有限的。过期可以基于消逝的秒数或者跳步(hop)的个数,对每次初始化命名空间的成功请求,跳步至少发生一次。

<?php
require_once 'Zend/Session/Namespace.php';

$s = new Zend_Session_Namespace('expireAll');
$s->a = 'apple';
$s->p = 'pear';
$s->o = 'orange';

$s->setExpirationSeconds(5, 'a'); // expire only the key "a" in 5 seconds

// 5 次访问后,会话过期
$s->setExpirationHops(5);

$s->setExpirationSeconds(60);
// 命名空间 "expireAll" 将在第一次访问后 60 秒,或者访问 5 次后过期。

在处理在当前请求中会话数据过期,需要小心来提取它们(会话数据)。尽管数据通过引用返回,修改数据将不使过期数据持续传递当前请求。为了“重置”过期时间,把数据放到临时变量,用命名空间来unset它们,然后再设置合适的键。

4.会话封装和控制器
命名空间可以被用来分离控制器对会话的访问,以免被污染。例如, 一个认证控制器可以为会议安全请求保持它的会话状态数据与其他控制器分离。

例 带有生命期的控制器命名空间会话

下面的代码,作为显示一个测试问题的控制器的一部分,初始化一个布尔变量来表示是否一个提交的答案应该被接受。在此例中,给用户300秒时间来回答所显示的问题。

<?php
// ...
// in the question view controller
require_once 'Zend/Session/Namespace.php';
$testSpace = new Zend_Session_Namespace('testSpace');
$testSpace->setExpirationSeconds(300, 'accept_answer'); // expire only this variable
$testSpace->accept_answer = true;
//...

下面,处理测试问题答案的控制器根据用户是否在允许的时间内提交答案来决定是否接受答案:

<?php
// ...
// in the answer processing controller
require_once 'Zend/Session/Namespace.php';
$testSpace = new Zend_Session_Namespace('testSpace');
if ($testSpace->accept_answer === true) {
    // within time
}
else {
    // not within time
}
// ...

5.防止每个命名空间有多重实例
Zend_Session_Namespace 能够防止给一个命名空间创建多个实例。

想要开启这个动作,当创建Zend_Session_Namespace的最后一个实例时,传递true给第二个构造函数参数。任何后来的初始化同一个命名空间的企图都会导致一个异常的抛出。

<?php
require_once 'Zend/Session/Namespace.php';

// create an instance of a namespace
$authSpaceAccessor1 = new Zend_Session_Namespace('Zend_Auth');

// create another instance of the same namespace, but disallow any new instances
$authSpaceAccessor2 = new Zend_Session_Namespace('Zend_Auth', true);

// making a reference is still possible
$authSpaceAccessor3 = $authSpaceAccessor2;

$authSpaceAccessor1->foo = 'bar';

assert($authSpaceAccessor2->foo, 'bar');

try {
    $aNamespaceObject = new Zend_Session_Namespace('Zend_Auth');
} catch (Zend_Session_Exception $e) {
    echo "Cannot instantiate this namespace since \$authSpaceAccessor2 was created\n";
}

上面构造函数的第二个参数告诉Zend_Session_Namespace任何之后带有”Zend_Auth”实例的命名空间都是不允许的。为了之后能够访问会话的命名空间,开发者需要给一个实例对象(如上面的例子中的$authSpaceAccessor1$authSpaceAccessor2或者$authSpaceAccessor3)存储一个引用。例如,开发者可以存储引用到一个静态变量或添加一个引用给一个registry。

6.使用数组
在PHP 5.2.1 版本之前,因为PHP魔术方法实现方法的历史原因,修改在命名空间里的数组是不可以的。如果你只使用PHP 5.2.1 或之前的版本,那么你可以跳到下一章节。

1.修改带有会话命名空间的数组数据

<?php
require_once 'Zend/Session/Namespace.php';
$sessionNamespace = new Zend_Session_Namespace();
$sessionNamespace->array = array();
$sessionNamespace->array['testKey'] = 1; // may not work as expected before PHP 5.2.1
echo $sessionNamespace->array['testKey'];

2.在会话存储之前构造数组

如果可以的话,可以通过在所有数组值被设置后存储数组到一个会话命名空间来完全避免问题的发生。

<?php
require_once 'Zend/Session/Namespace.php';
$sessionNamespace = new Zend_Session_Namespace('Foo');
$sessionNamespace->array = array('a', 'b', 'c');

如果你正使用有影响的PHP版本并需要在分配给一个会话命名空间的键之后修改数组,你可以用下面的其中之一或者全部的方案。

方案1:重新分配一个被修改的数组

在下面的代码中,创建、修改了一个被存储的数组的拷贝,并且重新从被创建的拷贝分配位置、重写原数组。

<?php
require_once 'Zend/Session/Namespace.php';
$sessionNamespace = new Zend_Session_Namespace();

// 分配初始数组
$sessionNamespace->array = array('tree' => 'apple');

// 拷贝数组
$tmp = $sessionNamespace->array;

// 修改拷贝数组
$tmp['fruit'] = 'peach';

// 将拷贝数组分配回会话命名空间
$sessionNamespace->array = $tmp;

echo $sessionNamespace->array['fruit']; // prints "peach"

方案2:存储包括引用的数组

在参数中直接储存一个数组的地址符,然后直接访问它。

<?php
require_once 'Zend/Session/Namespace.php';
$myNamespace = new Zend_Session_Namespace('myNamespace');
$a = array(1, 2, 3);
$myNamespace->someArray = array( &$a );//注意写法
$a['foo'] = 'bar';
echo $myNamespace->someArray['foo']; // prints "bar"

7.在对象中使用会话
如果你计划在PHP会话中保存对象,要知道它们将被系列化存储。而任何在PHP会话中保存的对象在从存储中取出时一定会被去系列化。这意味着开发者必须确保保存对象的类必须在对象从会话存储中被去系列化之前被定义。如果一个去系列化的对象的类没有被定义,那么它就变成一个数组对象(stdClass)的实例。

全局会话管理
会话的默认行为可以由 Zend_Session的一些静态方法来改变。使用Zend_Session来处理和操作所有的全局会话管理,包括使用Zend_Session_Core::setOptions() 方法对PHP内置的会话模块提供的常用配置选项的配置。但如果不能确保使用安全的save_path和PHP会话模块使用的唯一的cookie名,那么使用Zend_Session::setOptions() 可能会引发安全问题。

1.配置选项
当第一个会话命名空间被请求时,Zend_Session就会自动启动PHP会话,除非已经和Zend_Session::start()一起启动了。内部PHP的会话将会按照Zend_Session的默认配置开启,除非先前调用过Zend_Session::setOptions()修改了配置。

设置会话配置选项,包括基本名(在”session.”之后的名字部分)作为传递给Zend_Session::setOptions()的数组的键。数组里相应的值用来设置会话选项值。如果开发者没有设置选项,Zend_Session将首先使用推荐的默认选项,其次就是默认的php.ini设置。

例 使用Zend_Config配置Zend_Session
1.首先添加配置选项到INI文件:

; Accept defaults for production
[production]
; bug_compat_42
; bug_compat_warn
; cache_expire
; cache_limiter
; cookie_domain
; cookie_lifetime
; cookie_path
; cookie_secure
; entropy_file
; entropy_length
; gc_divisor
; gc_maxlifetime
; gc_probability
; hash_bits_per_character
; hash_function
; name should be unique for each PHP application sharing the same domain name
name = UNIQUE_NAME
; referer_check
; save_handler
; save_path
; serialize_handler
; use_cookies
; use_only_cookies
; use_trans_sid

; remember_me_seconds = <integer seconds>
; strict = on|off


; Development inherits configuration from production, but overrides several values
[development : production]
; Don't forget to create this directory and make it rwx (readable and modifiable) by PHP.
save_path = /home/myaccount/zend_sessions/myapp
use_only_cookies = on
; When persisting session id cookies, request a TTL of 10 days
remember_me_seconds = 864000

2.加载配置文件并传递它的数组表达给Zend_Session::setOptions():

<?php
require_once 'Zend/Config/Ini.php';
$config = new Zend_Config_Ini('myapp.ini', 'development');

require_once 'Zend/Session.php';
Zend_Session::setOptions($config->toArray());

上述大多数选项没有做解释,因为可以在PHP的官方文档中找到他们的解释,但特殊的选项注释如下:

boolean strict - 当使用new Zend_Session_Namespace时,禁止自动启动Zend_Session。

integer remember_me_seconds - 该选项指明了当用户代理结束(比如浏览器应用程序终止)后,会话标识符还将保存在cookie中的时长。

string save_path - 该值跟系统相关,开发者需提供一个PHP程序有读写权限的目录的绝对路径。如果可写的路径没有被提供,那么当启动时,Zend_Session 将抛出一个异常。(例如,当start()被调用)

[注意] 安全风险
如果其他应用程序有读这个目录路径的权限,那么就有发生会话劫持的可能性。如果其他应用程序有写这个目录路径的权限,那么就有发生会话污染的可能性。如果这个目录路径是与其他用户或PHP应用程序共享的,那么会引起大量的安全问题,包括会话数据盗窃,会话劫持,垃圾回收冲突(举例来说,另一个用户的PHP应用程序可能会删除你的应用程序的会话文件)。

例如,攻击者可以访问受害者的站点,获得会话cookie。在访问攻击者的站点执行var_dump($_SESSION)之前,他(攻击者)编辑cookie路径为在相同服务器上的他自己的域名。知道了有关受害者会话的详细信息,攻击者就可以修改受害者的会话状态(也就是会话中毒),把会话路径改回受害者的站点,然后使得来自受害者站点的请求使用已被污染了的会话。同个服务器上的两个应用程序不能读写对方应用程序的save_path,但如果save_path是可以猜测的,且攻击者拥有这2个站点其中一个的控制权,攻击者就可以修改他的站点会话的save_path为另一个站点的会话的save_path,从而就造成了会话污染。因此,save_path的值不能公开,且对每个应用程序必须是唯一的、安全的。

string name - 该值跟系统相关,开发者需为基于应用程序提供一个唯一的值。

[注意] 安全风险
如果php.ini中session.name的值是相同的(例如,默认为“PHPSESSID”),且在同个域名下面有两个及以上的PHP应用程序,那么当访问者访问这些站点时它们共享了会话数据。此外,很可能引起会话数据的破坏。

boolean use_only_cookies - 为了不引入更多的安全风险,不要修改该选项的默认值。

[注意] 安全风险
如果该选项没有被激活,攻击者使用攻击者站点上的链接,可以轻松的固定受害人的会话标识符,比如:http://www.example.com/index.php?PHPSESSID=fixed_session_id。假使受害者还没有一个example.com站点会话标识符的cookie,那么会话固定就成功了。一旦受害者使用了攻击者指定的会话标识符,那么攻击者就能劫持受害者的会话,并模仿受害者的用户代理,试图假装成受害者。

2.错误:Headers Already Sent
如果你看到错误信息,”Cannot modify header information - headers already sent” 或者 “You must call … before any output has been sent to the browser; output started in …”,那么仔细检查最近的和这信息有关联的原因(函数或方法)。任何请求发送HTTP头的动作,象发送一个cookie,必须在发送正常的输出(非缓冲输出)之前完成,除非使用PHP的输出缓冲。
①可以尝试重新安排应用程序逻辑,这样动作处理头被执行优先于发送任何输出。

②经常使用output buffering就能足够防止这个问题,并帮助提高性能。例如,在php.ini里,”output_buffering = 65535”允许有64K的缓冲。即使输出缓冲在生产服务器上提高性能是一个良好的策略,仅仅依靠缓冲来解决”headers already sent”还是不够。应用程序一定不能超过缓冲的大小,否则无论什么时候输出发送(先于HTTP头)超过缓冲的大小,问题就会发生。

③如果一个Zend_Session方法导致这个错误信息,仔细检查这个方法,并确保它的使用在应用程序中是必须的。例如,destroy() 默认的用法也发送HTTP头来使客户端的会话cookie过期。如果这不是必须的,那么使用destroy(false)。

④删除任何不在PHP文件末尾的结束标记”?>”,因为回车和其它在结束标记之后的可见的空白字符可以触发输出给客户端。

3.会话标识符
简介:在基于ZF的应用程序中有关会话使用的问题,提倡使用浏览器的cookie,而不是session。Zend_Session组件默认的只有cookie才能保持会话标识符。cookie的值是浏览器会话的唯一标识符。PHP内置的会话模块使用这个标识符以保持站点访问者与每个访问者的持久会话数据之间一对一的关系。Zend_Session组件包装了会话存储器($_SESSION)并提供了一个面向对象的接口。不幸的是,如果攻击者能访问受害者的cookie值(会话标识符),攻击者就能劫持受害者的会话。这个问题不仅在PHP中存在,在Zend Framework中也存在。regenerateId()方法能使应用程序重新生成会话标识符(储存在访问者的cookie中),标识符为一个随机的、不可预计的值。注意:虽然“用户代理(user agent)”和“Web浏览器(web browser)”不相同,为了使得本章节更易读,我们使用的这两个术语可以互换。

为什么?:如果攻击者获得了受害者有效的会话标识符,攻击者就可能假扮成一个有效的用户(受害者),得到了访问机密信息或者操作受害者在你的应用程序中的数据。更新会话标识符有利于阻碍会话劫持的发生。如果会话标识符改变了,攻击者就不知道新的会话标识,也就不能用新的会话标识劫持受害者的会话了。即使攻击者能够访问旧的会话标识,regenerateId()将会话数据从旧的标识符下移到了新的标识符下,所以通过旧的会话标识符访问不到会话数据。

何时使用regenerateId():在你的Zend框架程序引导文件中添加Zend_Session::regenerateId (),以最安全的方式重新生成用户Web浏览器cookie中的会话标识符。如果不需要有条件的判定何时重新生成会话标识符,那么这样的方式就没什么缺陷。虽然在每个请求中重新生成会话标识预防了几种攻击的途径,但是不是每个请求需要这么做。因此,应用程序通常设法动态的确定在有较大风险的情况下,重新生成会话标识符。当站点的访问者权限上升时(比如,访问者在编辑你的个人信息前,要重新验证用户)或者敏感的会话参数发生改变时,可以考虑使用regenerateId()创建新的会话标识符。如果你调用了rememberMe()之后,就不需要调用regeneraterId(),因为前者已经调用了后者。如果用户成功登录了站点,调用rememberMe()方法来取代调用regenerateId()方法。

3.1.会话劫持和会话固定
消除跨站脚本攻击(XSS)漏洞有利于防止会话劫持的发生。根据Secunia的统计,不管使用何种语言创建web应用程序,XSS问题经常发生。期望应用程序不存在跨站脚本攻击漏洞,还不如按照下面的最佳实践最小化损失,当攻击发生时。在跨站脚本攻击中,攻击者不需要直接访问受害者的网络。如果受害者已经存在一个会话 cookie,那么跨站脚本攻击的Javascript脚本会允许攻击者读取受害者的cookie并偷取会话。如果受害者还不存在会话cookie,利用跨站脚本攻击漏洞注入Javascript脚本,攻击者在受害者浏览器上创建一个已知会话标识符的cookie,然后在攻击者的系统中也创建同样的 cookie,这样就劫持受害者的会话。如果受害者访问了攻击者的站点,那么攻击者还能仿真受害者用户代理的一些其他特征。如果你的站点存在着XSS漏洞,攻击者就可能插入一段AJAX脚本,秘密的访问攻击者的站点,导致攻击者知道了受害者的浏览器特征,又知悉受害者站点的会话。然而,倘若站点开发者正确地设置了save_path选项,那么攻击者也不能任意地修改服务器端的PHP会话状态。

当第一次使用用户会话时,调用Zend_Session::regenerateId()不能防止会话固定攻击,除非你能辨别最初的会话是否是攻击者伪装成受害者。初听,这个跟前面所描述的是自相矛盾的,直到我们认为攻击者首先在你的站点上发起了一个真实的会话。如果会话第一次是被攻击者开启的,那么攻击者也就知道了初始化(regenerateId())后的结果(新的会话标识)。攻击者在XSS漏洞中使用这个新的会话标识,或者通过攻击者站点上的链接注入这个新的会话标识(只在use_only_cookies = off时有效)。

如果你能辨别使用相同会话标识符的受害者和攻击者,那么就可以直接处理会话劫持了。然而,这样的区分常常陷于可用性权衡的形式中,因为区别的方法常常是不严密的。举例来说,如果当前请求的IP与创建会话的请求的IP来自不同的国家,那么当前请求大概就是攻击者发起的。在以下的情形下,对于web应用程序就可能很难区别受害者和攻击者了:

  • 攻击者首先在你的站点上发起一个会话,以获得一个合法的会话标识符

  • 攻击者利用你的站点上的XSS漏洞,在受害者的浏览器上创建具有相同标识符且有效的会话cookie(也就是会话固定)

  • 受害者和攻击者来自同一个上网代理(比如他们都处于一个大公司的同一个防火墙后面,像AOL)

下面的代码使得攻击者很难获得受害者当前的会话标识符,除非攻击者已经完成上面的第一二两步。

例 防范会话固定

<?php
require_once 'Zend/Session/Namespace.php';
$defaultNamespace = new Zend_Session_Namespace();

if (!isset($defaultNamespace->initialized)) {
    Zend_Session::regenerateId();
    $defaultNamespace->initialized = true;
}

4.rememberMe(integer $seconds)
通常,用户代理结束时,会话也就结束了,比如当用户退出浏览器。然而,你的应用程序可能需要保留SESSION一段时间,该方法被用来设置会话结束后SESSION保存的时间。如果你没有指定秒数,那么会话cookie的生命期默认为remember_me_seconds,它可以用Zend_Session::setOptions()来设置。为了帮助阻止会话固定/劫持,当用户成功地通过你的程序的认证,使用这个函数(例如,从一个“登录”表单)。

5.forgetMe()
此函数补充了rememberMe(),当用户代理终止时,写入一个有结束生命期的会话cookie。

6.sessionExists()
这个方法用来确定当前用户请求是否已经存在会话。这个方法可在会话开启之前使用,且这个方法独立于与Zend_Session和Zend_Session_Namespace的其他方法。

7.destroy(bool $remove_cookie = true, bool $readonly = true)
Zend_Session::destroy(),删除当前会话的所有数据。然而,PHP中的变量还未知情,所以你的会话命名空间(Zend_Session的实例)还是可读的。为了完成“登出”动作,设置可选的参数为true(默认为true)来删除用户代理端的会话cookie。可选的$readonly参数销毁了创建新的Zend_Session_Namespace实例和为Zend_Session方法写入会话数据存储的能力。

如果你看到错误信息”Cannot modify header information - headers already sent” , 那么要么避免使用true 作为第一个参数(会话cookie的请求删除),要么参考 “错误:Headers Already Sent” 。这样,Zend_Session::destroy(true) 一定要么在PHP发送HTTP头之前被调用,要么输出缓冲被允许。并且,为防止触发在调用destroy()之前发送输出,输出发送的总数不能超过缓冲的大小。

8.stop()
这个方法只是更改了Zend_Session中的一个标志位,以阻止之后向会话数据存储器中写数据。当程序的执行转移到视图相关的代码上时,为免滥用,临时关闭Zend_Session_Namespace实例和Zend_Session中的方法向会话数据存储器写数据的能力。

9.writeClose($readonly = true)
关闭会话,把$_SESSION数组中的数据写到后台的存储器中(文件、数据库),完成内部数据的转换。

[注意]默认地,$readonly是被激活的,之后写会话数据的动作,将会抛出一个异常。

10.expireSessionCookie()
该方法向客户端发送一个过期的会话cookie,以引起客户端删除会话cookie。通常这个技术被用来执行客户端登出请求。

11.setSaveHandler(Zend_Session_SaveHandler_Interface $interface)
对于大多数开发者来说默认的save handler已经足够了,这个方法只是以面向对象的方式包装了一下session_set_save_handler()函数,可以自定义会话存储函数来将会话数据存储到数据库。

12.namespaceIsset($namespace)
这个方法用来检查某会话命名空间是否存在,或者某会话命名空间下的某个索引是否存在。

[注意] 如果Zend_Session没有被标记为可读(比如在Zend_Session开启之前),将会抛出一个异常。

13.namespaceUnset($namespace)
使用namespaceUnset($namespace)注销某个命名空间及其内容,而不用为某个命名空间创建Zend_Session实例,然后迭代它删除每个条目。如果被注销的变量为数组,且该数组包含了其他对象,而这些对象又被其他变量引用,这些对象仍然是可访问的。不要期望namespaceUnset方法会“深”注销/删除命名空间下条目的内容。

[注意] 如果命名空间不可读(比如执行了destroy()之后),将会抛出一个异常。

14.namespaceGet($namespace)
不建议在Zend_Session_Namespace中用getIterator()。 这个方法返回$namespace命名空间的内容数组$name。

[注意] 如果Zend_Session没有被标记为可读(比如在Zend_Session开启之前),将会抛出一个异常。

15.getIterator()
使用getIterator()方法,可获得一个包含所有命名空间名字的数组。

[注意] 如果Zend_Session没有被标记为可读(比如在Zend_Session开启之前),将会抛出一个异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值