IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Open source  >

使用 CakePHP 快速打造 Web 站点,第 4 部分: 使用 CakePHP 的 Session 和 Request Handler 组件

使 PHP 应用程序更加流线化

developerWorks
前一页第 3 页,共 9 页后一页

文档选项

样例代码


对本教程的评价

帮助我们改进这些内容


会话处理

当向 Web 站点发出请求时,该请求完全独立于之前发出的每个请求。为了实现用户功能,特定的 Web 客户机需要重复访问一些惟一的、可能需要保密的信息。这在 Web 应用程序中被称为会话处理(session handling),而正确处理会话的细微之处令很多开发人员头疼。

会话处理的基本原理

在所有编程语言中,会话处理的基本原理都是相同的。在首次访问 Web 站点时,客户机被授予一个惟一的 ID,这个 ID 通常存储在 cookie 中。在服务器端,以某种方式存储一个变量数组,该数组与惟一 ID 相对应。对于同一个客户机发出的任何后续请求,这个惟一 ID 会随请求一同发送,服务器根据这个 ID 把数组装入内存。这些变量被称为客户机的会话变量(session variable)。在 PHP 中,它们被存储在 $_SESSION 全局变量中。

在使用 CakePHP 时,只需使用 $_SESSION 全局变量即可访问会话信息。但是,CakePHP 附带自己的会话处理对象,正如我们稍后将要看到的,这个会话处理对象有很多优点。





回页首


Tor 中的会话处理

不用费多大气力就可以实现会话。当用户登录时,UsersController 对象存储用户名,并在后续请求期间将其与客户机自动关联起来。

每个 Controller 对象(继承自 AppController 的任何对象)都自动具有对 Session 组件的访问权。回想一下:组件是一个与控制器相关联的类(允许附加功能),很像是为视图提供附加功能的 helper。在第 2 部分中添加 ACL 时,使用了 ACL 组件。需要将以下行添加到 ProductsController 类和 UsersController 类的开头:var $components = array('Acl');

虽然会话处理在 CakePHP 中是一个组件,但它是每个控制器都包含的标准组件,因此无需将其添加到组件列表中。

要使用 Session 组件,只需访问控制器中的会话实例变量。会话处理程序的两大关键功能就是设置变量和获取变量,这些功能是通过调用 read 方法和 write 方法来实现的。在用户登录时,使用清单 7 中的代码把当前客户机的用户名写入会话中。这段代码位于 UsersController 类中。


清单 7. 使用 write 方法存储用户名
                    
function login()
{
  ...

  $this->Session->write('user', $this->data['User']['username']);

  ...
{

write 方法接受两个参数。第一个参数是指定的键,第二个参数是分配给该键的值。在本例中,键为 user,而值是输入的用户名。稍后将访问该用户名(见清单 8)以根据 ACL 检查是否可以查看或编辑产品。


清单 8. 使用 read 方法访问用户名
                    
function view($id) {
  ...

  if ($this->Acl->check($this->Session->read('user'), 
$id.'-'.$product['Product']['title'], 'read'))
  {
    ...
  }
}

read 方法接受一个参数 — 需要访问的键 — 并返回存储的值。





回页首


存储会话

所有这些做法对于 Web 开发人员来说应当都不算是什么新闻,但是会话处理对于小型应用程序来说通常只是一个小问题。如果应用程序要求在会话中存储敏感的用户信息,例如密码或信用卡信息,则存储数据的位置和方法就极其重要了。

在 CakePHP 中,会话存储是由一行来控制的:Configure::write('Session.save', 'php');。这一行(位于 /app/config/core.php 文件中)告诉 CakePHP 应该如何存储会话。有三个有效值:php(使用 php.ini 文件中的设置)、cake(将会话文件保存在 CakePHP 的 tmp 目录中)和 database(使用 CakePHP 的数据库会话)。





回页首


存储会话:cake

设置此值时,将把会话作为文件存储在应用程序文件夹中。CakePHP 在 /app/tmp/session 提供了一个文件夹,其中包含诸如 sess_50bfa744a2ab2c98df808f70c893704c 之类的文件。在这些文件中,各个会话变量被存储为明文而不进行加密。

Apache Web 服务器有一个名为安全模式的设置,它限制 Apache 可以访问的文件夹。通常,Apache 只可以读取站点的文档根目录中的内容,但是一些库文件例外。在本系列中,在安装 CakePHP 时将整个目录放在 Apache 的文档根目录中(/webroot 目录)。这肯定是一种比较轻松的安装方式,但是不太安全,原因如下:通过将会话处理设置为 cake,将把会话变量存储到一个目录中,浏览器可以直接访问这个目录。如果站点遭受到某种攻击,攻击者可以让 Apache 返回任意文件,则每个用户的会话数据都容易受到攻击(尽管这个问题可能不是您最担心的)。CakePHP 为保护这些会话文件采取了很好的措施(即使它们在文档根中),但是在理想情况下让 app/webroot 目录成为文档根目录会更安全。这会使 CakePHP 会话文件离线。

必须注意,您无法控制对于这些会话文件的权限。它们将拥有与授予 PHP 的权限完全相同的用户权限和组权限。在某些系统中,这也可能是安全漏洞。

优点

  • 会话变量被存储在 CakePHP 中,因而整个应用程序都位于同一位置。
  • 可以用文本浏览器读取会话文件,可能用于调试(可能没用)。
  • 启动和访问会话不要求使用数据库连接(可能没有帮助,因为在 CakePHP 中访问模型将启动一个 PHP 会话)。

缺点

  • 会话文件被存储在文档根目录中,可能会在 Web 服务器受到危及时也遭到波及。
  • 会话文件拥有与 PHP 相同的权限。
  • 不共享一个文件系统的负载平衡的 Web 服务器不能共享对会话文件的访问权,导致会话被神秘地删除,除非使用粘性会话(sticky session)。




回页首


存储会话:database

如果要存储的会话信息需要更高的安全级别,或更有力的权限控制,则使用数据库会话会更好。通过将 Session_save 设置为 database,告诉 CakePHP 在应用程序的其余部分中,把所有序列化的变量信息存储到数据库的表中。

在通过 CakePHP 使用数据库会话之前,必须先创建表。您应当放心大胆地在 Tor 中进行尝试。默认情况下,表名为 cake_sessions,不过此名称可以在 app/config/core.php 文件中更改。为了使用数据库会话存储,需要取消 Session.table 和 Session.database 的 Configure::write 行的注释标志。这个表的模式存储在 app/config/sql/sessions.sql 中。CakePHP V1.2.0.x 提供的模式如下:


清单 9. 创建表 cake_sessions
                    
CREATE TABLE cake_sessions (
  id varchar(255) NOT NULL default '',
  data text,
  expires int(11) default NULL,
  PRIMARY KEY  (id)
);

在创建了表并把 Session.save 设置为 database 之后,请尝试在 /users/login 登录到 Tor 中。登录后,检查数据库中是否出现了您的会话。应当会出现一行类似如下所示的内容:

id                                 data                                expires
50bfa744a2ab2c98df808f70c893704c   Config|a:3:{s:4:"rand";i:94427...   1164661678

把会话存储到数据库中将直接解决前面列出的三个缺点。第一,Apache 通常对数据库没有直接访问权,所以 Web 服务器遭到入侵时不会暴露会话信息。第二,可以为应用程序明确设置对数据库的访问权限,甚至可以将访问限定于特定的主机。第三,负载平衡的服务器共享对会话表的访问权,而无需您做任何额外的工作。

对于大多数大型应用程序,数据库会话是很合适的,因为它们提供最大程度的安全性而只需投入最少的精力。

优点

  • 易于设置 — 只要求在数据库中添加一个附加表。
  • Web 服务器遭到入侵时可能不会危及会话的安全性。
  • 可以在负载平衡的服务器之间轻松地共享会话。

缺点

  • 使用数据库存储会话会增加数据库的开销。
  • 会话仍以明文的形式存储在数据库中;数据库备份可能会导致敏感数据被长时间存储。
  • 根据数据库设置方式的不同,应用程序与数据库之间的通信可能不安全。如果数据库不是位于本地主机上,或者不是通过安全通道(例如 VPN)进行通信,则通信很可能会受到危及。




回页首


存储会话:php

存储会话的最后一种方法是使用 PHP 设置的会话处理方法。默认情况下,PHP 将把其会话写到类似于 Session.savecake 设置的文件中。一个主要差别是,会话变量不是保存在文档根目录中,而通常是保存在文件系统中其他地方的一个临时目录中。与将会话存储在站点所在的同一个目录中相比,这可能更好,也可能不好。

通过把会话设置为通过 PHP 存储,可以更好地控制会话。PHP 允许重写一些会话处理程序函数,从本质上将存储会话的方法重写为您选择的方法。例如,通过一个定制的安全通道将会话存储在单独的数据库中,或者您能想到的任何 “疯狂” 的方法。

如果需要更改 PHP 采用的会话处理方法,可以使用函数 session_set_save_handler,该函数可以控制会话回调函数。向此函数传递用来打开、关闭、读取和写入会话的函数的名称。深入讨论 session_set_save_handler 函数超出了本教程的讨论范围(请参阅 参考资料)。


清单 10. 重新定义 PHP 存储会话的方法
                    
function open($save_path, $session_name)
{
  global $sess_save_path;
 
  $sess_save_path = $save_path;
  return(true);
}

function read($id)
{
  global $sess_save_path;
 
  $sess_file = "$sess_save_path/sess_$id";
  return (string) @file_get_contents($sess_file);
}

...

session_set_save_handler("open", "close", "read", "write", "destroy", "gc");

会话处理函数由 PHP 函数 session_start() 重新定义的。使用此方法有以下优点。

优点

  • 极大的灵活性 —— 可以使用 PHP 支持的任何存储方法。
  • 如果不重写会话处理函数,则会话将按照与服务器上所有其他应用程序一样的方法来存储。

缺点

  • 由于 PHP 默认设置为把会话存储在临时目录中,因此您要面对 “存储会话:'cake'” 中提到的一些缺点。

选择会话存储方法并不总是很容易。在大多数情况下,让 PHP 处理会话就可以了。但是从根本上说,应该根据应用程序的具体情况做出决策。

在下一节中,我们将讨论 Request Handler 组件,以及如何使用它在应用程序中添加 Ajax 功能。





回页首



前一页第 3 页,共 9 页后一页
    关于 IBM 隐私条约 联系 IBM 使用条款