16章 Drupal会话(session)(1)

会话(session)
译者:葛红儒 ESKALATE科技公司
HTTP是一个无状态协议,这意味着浏览器和服务器之间的每次交互都是相互独立的。那么你如何追踪一个用户(他或她)对一个网站的页面的一系列的访问呢?使用会话(session)。
从PHP4开始,通过一组会话函数,PHP提供了对会话的内置支持。在本章,你将看到Drupal是如何使用PHP的会话的。
 
什么是会话?
当一个浏览器第一次请求一个Drupal站点的页面时,PHP会向浏览器发送一个cookie,它包含了一个随机生成的长为32位的字符串ID,默认称之为PHPSESSID。在浏览器第一次访问一个站点时,返回的HTTP头部信息中的一行包含了PHPSESSID,如下所示:
HTTP/1.1 200 OK
Date: Wed, 17 Jan 2007 20:24:58 GMT
Server: Apache/1.3.33 (Darwin) PHP/5.1.6
Set-Cookie: PHPSESSID=3sulj1mainvme55r8udcc6j2a4; expires=Fri, 09 Feb 200723:58:19
GMT; path=/
Last-Modified: Wed, 17 Jan 2007 20:24:59 GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
在接下来的访问中,浏览器将cookie放到每个HTTP请求中,以向服务器出示cookie。
GET / HTTP/1.1
User-Agent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.1)
Gecko/20061204 Firefox/2.0.0.1
Cookie: PHPSESSID=3sulj1mainvme55r8udcc6j2a4
这允许PHP追踪一个单独的浏览器对站点的访问。长为32位的字符串ID,用作会话ID,它作为Drupal存储的关于会话信息的键来使用,同时使得Drupal将会话于独立用户联系起来。
 
用法
Drupal在多个重要的内部函数中使用会话(session)来存储临时信息,比如独立用户的状态或喜好。例如,drupal_set_message()需要为用户传递状态或者错误信息,从错误发生的页面传递到下一个页面。在这里,我们将信息存储在一个位于用户会话中的名为messages的数组里面,从而完成传递的。
 另一个例子来自于comment.module,在这里使用会话(session)存储用户的查看喜好:
$_SESSION['comment_mode'] = $mode;
$_SESSION['comment_sort'] = $order;
$_SESSION['comment_comments_per_page'] = $comments_per_page;
 当预览节点时,Drupal也使用会话(session)来保存上传文件。当在Administer ➤
Content management ➤ Content页面,过滤站点内容时,Drupal用会话记住用户浏览喜好。还有在安装和更新系统中,也使用了会话(install.php和update.php).
Drupal为登录用户和匿名用户都创建了会话。对于匿名用户,在表sessions中有一行记录,其中列uid设置为0.由于会话是特定于浏览器的(它们于浏览器的cookie绑定在一起),这样,在同一个计算机上打开多个浏览器就会有多个会话。
 
 
警告:在匿名用户第一次访问一个站点时,Drupal并不为其存储会话信息,这是为了在网络爬虫和机器人访问站点时避免向表sessions插入大量数据。对于开发者来说,这意味着你不能为匿名用户的初次访问存储会话信息。
 
会话(session)中的真实信息存储在表sessions的session列中。当PHP的会话垃圾收集器周期性运行时,会自动清理sessions表。表中记录的最长存在周期由settings.php中的session.gc.maxlifetime决定。如果用户退出,那么与之相关的会话记录将被立即从数据库中清除。注意,如果一个用户通过多个浏览器(而不是浏览窗口)或者多个IP地址同时登录的话,那么每个浏览器都有一个会话;因此,从一个浏览器退出不影响其它的浏览器。
 
 
会话相关设置
可以在Drupal中的3个地方修改会话设置,在.htaccess文件中,在settings.php文件中,在includes/bootstrap.inc文件中的引导指令代码里。
 
在.htaccess文件中
在Drupal的默认文件.htaccess中使用下面一行代码关闭PHP的session.auto_start功能,这样就确保了在会话启动后,Drupal对它的完全控制能力。代码如下:
php_value session.auto_start                0
 
session.auto_start是一个PHP在运行时不能改变的配置选项,这就是将其放置在这里而不是settings.php中的原因。
 
在settings.php文件中
在settings.php里面,你将设置大部分会话相关的设置选项。该文件位于sites/default/
settings.php或者sites/example.com/settings.php。
ini_set('session.cache_expire',     200000); // 138.9 days
ini_set('session.cache_limiter',    'none');
ini_set('session.cookie_lifetime', 2000000); // 23.1 days
ini_set('session.gc_maxlifetime',   200000); // 55 hours
ini_set('session.save_handler',    'user'); // Use user-defined session handling.
ini_set('session.use_only_cookies',     1); // Require cookies.
ini_set('session.use_trans_sid',        0); // Don't use URL-based sessions.
 
将这些设置放在这里而不是.htaccess文件里,这就使得子站点可以拥有不同的设置,并且允许Drupal在PHP作为CGI运行时修改会话设置(PHP的.htaccess中的指令不能这样修改)。
    Drupal使用函数ini_set('session.save_handler', 'user')来覆盖由PHP提供的默认会话处理器,并实现了它自己的会话管理。user-defined在这里的意思是“Drupal定义的”(参看http://www.php.net/manual/en/function.session-set-save-handler.php)。
 
 
在bootstrap.inc文件中
PHP提供了内置的会话处理函数,如果你想实现自己的会话处理器,PHP允许你覆写这些函数。PHP继续处理cookie管理,而Drupal则实现后台的会话存储。
 
在引导指令中的DRUPAL_BOOTSTRAP_SESSION阶段中的下列代码,将处理器设置为includs/session.inc里面的函数,并启动会话处理:
require_once variable_get('session_inc', './includes/session.inc');
session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write',
'sess_destroy_sid', 'sess_gc');
session_start();
个别时候,一个文件内部的函数命不使用文件名作为前缀,这里就是这样。你可能会认为前面的函数应该为session_open,session_close等等。由于PHP在该命名空间下有了这些函数,所以这里是用简写前缀名sess。
注意,包含进来的文件是通过一个Drupal变量来定义的,这意味着你完全可以实现自己的会话处理并将其插入进来以代替Drupal的默认会话处理。例如,你可以使用内存数据库来实现函数'sess_open'、 'sess_close'、 'sess_read'、 'sess_write'、'sess_destroy_sid'、 'sess_gc',并将代码保存到名为inmemorysessions.inc的文件中。将Drupal变量session_inc设置为你自己的会话代码:
<?php
variable_set('session_inc', './sites/all/inmemorysessions.inc');
?>
 
cookie的必要性
如果浏览器不接受cookie的话,那么就建立不了会话。这是因为PHP指令sessions_use_only_cookies被设置为1,通过将sessions.use_trans_sid设置为0,其可选项(在URL的查询字符串中传递PHPSESSID)也被禁用。这种方式是Zend所推荐的:
 
基于URL的会话管理于基于cookie的相比,安全性更差一些。例如,用户可能向朋友发送一封email,其中带有了一个包含了处于激活状态的会话ID的URL,或者用户可能将一个包含了会话ID的URL保存在他们的书签里,之后再使用同一会话ID来访问你的站点。
 
当PHPSESSID出现在一个站点的查询字符串中时,它标志着主机提供商已经锁住了PHP,并且不允许通过ini_set()函数在运行时设置PHP指令。可选的一种替代方式是将设置选项移到
.htaccess文件中(如果在主机上,PHP是作为Apache的一个模块运行的话)或者一个本地php.ini文件中(如果在主机上,PHP是作为一个可执行的CGI运行时)。
 为了阻止会话欺诈,当用户登录时会重新生成会话ID(参看modules/user/user.module里的user_login_submit()函数)。
 
存储
会话信息存储在表sessions中,在引导指令的DRUPAL_BOOTSTRAP_SESSION阶段,它将会话ID和Drupal用户ID关联了起来(参看第15章以学习关于Drupal引导指令处理流程的更多知识)。事实上,在Drupal中广泛使用的对象$user,就是在本阶段使用includes/session.inc里面的方法sess_read()初步建立的。
下面是用于存储会话的表结构:
CREATE TABLE {sessions} (
uid int unsigned NOT NULL,
sid varchar(64) NOT NULL default '',
hostname varchar(128) NOT NULL default '',
timestamp int NOT NULL default '0',
cache int NOT NULL default '0',
session longtext,
KEY uid (uid),
PRIMARY KEY (sid),
KEY timestamp (timestamp)
) /*!40100 DEFAULT CHARACTER SET UTF8 */
当Drupal提供一个页面时,最后一项工作就是将会话写到表sessions中(参看includes/session.inc里面的sess_write())。只有当浏览器提供了一个有效的cookie时,才这样做,这是为了阻止网络爬虫对页面抓取时向表sessions中写入大量数据。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值