会话

    会话的配置保存在 Configure 中,位于顶级的 Session 键之下,有一些选项可用:

    • Session.cookie - 改变 session cookie 的名字。
    • Session.timeout - 分钟 数,之后 CakePHP 的会话处理器(session handler)会让会话过期。这会影响到 Session.autoRegenerate (见下),是由 CakeSession类处理的。
    • Session.cookieTimeout - 分钟 数,之后 session cookie 会过期。如果没有定义,会使用和 Session.timeout 同样的值。这会影响到 session cookie,是由 PHP本身处理的。
    • Session.checkAgent - 是否应当对每个请求检查用户代理。如果用户代理不匹配,会话就会被销毁。
    • Session.autoRegenerate - 开启该设置,就会打开会话的自动延期,导致频繁变化的会话标识(id)。开启该值,会使用会话的 Config.countdown 值来跟踪请求(数量)。一旦倒计数达到 0,会话标识(id)就会重新生成。对于由于安全原因而需要频繁改变会话标识的应用程序,这是很好的选项。你可以通过改变CakeSession::$requestCountdown 来控制重新生成会话所需要的请求数。
    • Session.defaults - 让你可以使用内置默认会话配置之一作为会话配置的基础。
    • Session.handler - 让你定义定制会话处理器。核心的数据库和缓存会话处理器使用该选项。这个选项代替了旧版本的 Session.save。后面有会话处理器的更多信息。
    • Session.ini - 让你可以设置配置中的额外的会话 ini 设置。这和Session.handler 一起代替了旧版本的自定义会话处理功能。
    • Session.cacheLimiter - 让你可以定义用于会话 cookie 的缓存控制表头。默认为must-revalidate。该选项在 2.8.0 中加入。
      当应用程序使用 SSL协议时,CakePHP 默认设置 为 true。如果应用程序同时使用 SSL 和非 SSL 协议,你也许会有会话丢失的问题。如果你要在 SSL和非 SSL 域中访问会话,就应该关闭这个:

    在 2.0 版本中,Session cookie 路径默认是 /,要改变它,可以设置session.cookie_path ini 标识为应用程序的目录路径:

    1. Configure::write('Session', array(
    2. 'defaults' => 'php',
    3. 'ini' => array(
    4. 'session.cookie_path' => '/app/dir'
    5. )
    6. ));

    如果你使用PHP的默认会话设置,注意session.gc_maxlifetime会覆盖你对超时的设置。默认值为24分钟。在ini设置中改变该设置来获得较长时间的会话:

    1. Configure::write('Session', array(
    2. 'defaults' => 'php',
    3. 'timeout' => 2160, // 36 小时
    4. 'ini' => array(
    5. 'session.gc_maxlifetime' => 129600 // 36 小时
    6. )
    7. ));

    CakePHP 自带几个内置的会话配置。你可以用这些作为配置的基础,也可以创建完全自定义配置。要使用默认配置,只需把'defaults' 键设置为你要使用的默认配置的名称。然后你就可以在 Session 配置中声明任何子设置来覆盖它:

    1. Configure::write('Session', array(
    2. 'defaults' => 'php'
    3. ));

    上面的代码使用内置的 'php' 会话配置。你象下面这样增强部分或全部配置:

    1. Configure::write('Session', array(
    2. 'defaults' => 'php',
    3. 'cookie' => 'my_app',
    4. 'timeout' => 4320 //3 天
    5. ));

    上面的代码会覆盖 'php' 会话配置的 timeout 和 cookie 名称。内置的配置如下:

    • php - 以 php.ini 文件中的标准设置保存会话。
    • database - 使用内置的数据库会话。欲知详情,请参看后面的部分。
    • cache - 使用内置的缓存会话。欲知详情,请参看后面的部分。

    会话处理器也可以定义在会话配置数组中。定义之后,它们让你可以把各种session_save_handler 值映射到你要用来保存会话的类或对象。有两种方式使用'处理器'。第一种是提供含有 5 个 callable 的数组。然后这些 callable 应用于session_set_save_handler:

    你也可以在插件内使用会话处理器。只需把引擎设置为类似MyPlugin.PluginSessionHandler 这样。这会加载和使用应用程序中 MyPlugin 插件内的 PluginSessionHandler 类。

    该接口用于 CakePHP 中所有的自定义会话处理器,而且可以用来创建自定义的用户会话处理器。只需在类中实现该接口,并设置创建的类名为 Session.handler.engine。CakePHP 会尝试从 app/Model/Datasource/Session/$classname.php 内加载处理器。所以如果类名为 AppSessionHandler,文件就应当是app/Model/Datasource/Session/AppSessionHandler.php

    会话配置的变化改变了如何定义数据库会话。大多数情况下只需在配置中设置Session.handler.model,以及选择数据库默认值:

    1. Configure::write('Session', array(
    2. 'defaults' => 'database',
    3. 'handler' => array(
    4. 'model' => 'CustomSession'
    5. )
    6. ));

    以上代码会告诉 CakeSession 使用内置的 'database' 默认值,并且指定叫做CustomSession 的模型负责保存会话信息到数据库中。

    如果你不需要完全自定义的会话处理器,但是仍然要求以数据库为基础保存会话,可以简化上述代码为:

    1. Configure::write('Session', array(
    2. 'defaults' => 'database'
    3. ));

    这样的配置会要求增加一个数据库表,含有至少这些字段:

    1. CREATE TABLE `cake_sessions` (
    2. `id` varchar(255) NOT NULL DEFAULT '',
    3. `data` text,
    4. `expires` int(11) DEFAULT NULL,
    5. PRIMARY KEY (`id`)
    6. );

    你也可以使用 schema 命令行用默认应用程序骨架中提供的数据结构文件来创建该表:

    1. $ Console/cake schema create sessions

    要使用基于缓存的会话,可以这样配置会话:

    这会配置 CakeSession 使用 CacheSession 类负责保存会话。可以用 'config' 指定使用哪个缓存配置。默认的缓存配置为 。

    内置的默认值试图为会话配置提供共同的基础。你也许还需要调整特定的 ini 设置。CakePHP 提供了为默认配置和自定义配置自定义 ini 设置的功能。会话设置中的 ini键让你可以指定单个配置的值。例如你可以用它来控制象 session.gc_divisor 这样的设置:

    1. Configure::write('Session', array(
    2. 'defaults' => 'php',
    3. 'ini' => array(
    4. 'session.gc_divisor' => 1000,
    5. 'session.cookie_httponly' => true
    6. )
    7. ));

    在 CakePHP 中创建自定义会话处理器(session handler)是直截了当的。在下面的例子中,我们会创建一个会话处理器,把会话保存在缓存(apc)和数据库中。这给我们 apc 的高速IO 的好处,而不必担心缓存满了时会话会逐渐丢失。

    首先我们需要创建自定义类,把它放在app/Model/Datasource/Session/ComboSession.php。该类应该象这样:

    1. App::uses('DatabaseSession', 'Model/Datasource/Session');
    2.  
    3. class ComboSession extends DatabaseSession implements CakeSessionHandlerInterface {
    4. public $cacheKey;
    5.  
    6. public function __construct() {
    7. $this->cacheKey = Configure::read('Session.handler.cache');
    8. parent::__construct();
    9. }
    10.  
    11. // 从会话读取数据。
    12. public function read($id) {
    13. $result = Cache::read($id, $this->cacheKey);
    14. if ($result) {
    15. return $result;
    16. return parent::read($id);
    17. }
    18.  
    19. // 向会话写入数据。
    20. public function write($id, $data) {
    21. Cache::write($id, $data, $this->cacheKey);
    22. return parent::write($id, $data);
    23. }
    24.  
    25. // 销毁一个会话。
    26. public function destroy($id) {
    27. Cache::delete($id, $this->cacheKey);
    28. return parent::destroy($id);
    29. }
    30.  
    31. // 清除过期的会话。
    32. public function gc($expires = null) {
    33. Cache::gc($this->cacheKey);
    34. return parent::gc($expires);
    35. }
    36. }

    我们的类扩展了内置的 DatabaseSession 类,所以我们不需要重复它全部的逻辑和行为。我们用 Cache 操作包裹每个操作。这让我们从高速的缓存读取会话,而不必担心填充缓存时会怎样。使用这个会话处理器也容易。在 core.php 文件中象下面这样修改会话设置块:

    1. Configure::write('Session', array(
    2. 'defaults' => 'database',
    3. 'handler' => array(
    4. 'engine' => 'ComboSession',
    5. 'model' => 'Session',
    6. 'cache' => 'apc'
    7. )
    8. ));
    9.  
    10. // 确保添加 apc 缓存配置
    11. Cache::config('apc', array('engine' => 'Apc'));

    现在应用程序会开始使用自定义会话处理器来读写会话数据了。

    • class CakeSession
    • static CakeSession::read($key)
    • 可以使用与 Set::classicExtract() 兼容的语法从会话读取值:
    1. CakeSession::read('Config.language');
    • static CakeSession::write($key, $value)
    • $key 应当是希望写入 $value 的以点分隔的路径:
    • static CakeSession::($key)
    1. CakeSession::delete('Config.language');

    你还应当阅读 和SessionHelper,来了解如何在控制器和视图中访问会话数据。