当你关注于防止源码的暴露时,你的会话数据只同样存在着风险。在默认情况下,SESSION保存在/tmp目录下。这样做在很多情形下是很方便的,其中之一是所有用户都有对/tmp的写入权限,这样Apache同样也有权限进行写入。虽然其他用户不能直接从shell环境读取这些会话文件,但他们可以写一个简单的脚本来进行读取:

01 <?php
02  
03 header('Content-Type: text/plain');
04 session_start();
05  
06 $path ini_get('session.save_path');
07 $handle = dir($path);
08  
09 while ($filename $handle->read())
10 {
11   if (substr($filename, 0, 5) == 'sess_')
12   {
13     $data file_get_contents("$path/$filename");
14  
15     if (!empty($data))
16     {
17       session_decode($data);
18       $session $_SESSION;
19       $_SESSION array();
20       echo "Session [" substr($filename, 5) . "]\n";
21       print_r($session);
22       echo "\n--\n\n";
23     }
24   }
25 }
26  
27 ?>

这个脚本在session.save_path所定义的会话文件保存目录中搜索以sess_为前缀的文件。找到文件后,即对它的内容进行解析并用print_r()函数显示它的内容。这样其它开发者就容易地取得了你的用户的会话数据。

解决这个问题的最好方法是把你的会话数据存入用用户名和密码保护的数据库中。由于数据库的访问是受控的,这样就多了一层额外的保护。通过应用前节中提及的技巧,数据库可以为你的敏感数据提供一个安全的存放地,同时你应该保持警惕,你的数据库安全性正变得越来越重要。

为在数据库中保存会话数据,首先需要建立一个数据表:

1 CREATE TABLE sessions
2 (
3   id varchar(32) NOT NULL,
4   access int(10) unsigned,
5   data text,
6   PRIMARY KEY (id)
7 );

如果你使用的是MySQL,则表结构描述如下:

1 mysql> DESCRIBE sessions;
2 +--------+------------------+------+-----+---------+-------+
3 | Field  | Type             | Null | Key | Default | Extra |
4 +--------+------------------+------+-----+---------+-------+
5 | id     | varchar(32)      |      | PRI |         |       |
6 | access | int(10) unsigned | YES  |     | NULL    |       |
7 | data   | text             | YES  |     | NULL    |       |
8 +--------+------------------+------+-----+---------+-------+

如要使会话数据能保存在此表中,你需要使用session_set_save_handler( )函数来编辑PHP的内建会话机制:

01 <?php
02  
03 session_set_save_handler('_open',
04                          '_close',
05                          '_read',
06                          '_write',
07                          '_destroy',
08                          '_clean');
09  
10 ?>

以上的六个参数每一个都代表着需要你编写的函数的名称,他们对下面的任务进行处理:

  • 打开会话存储
  • 关闭会话存储
  • 读取会话数据
  • 写入会话数据
  • 消灭会话数据
  • 清除旧会话数据

我有意使用了有意义的名称,这样你可以一下看出它们的目的。命名是任意的,但你可能希望用下划线开头(如此处所示)或其它的命名约定来防止名称冲突。下面是这些函数(使用MySQL)的示例:

01 <?php
02  
03 function _open()
04 {
05   global $_sess_db;
06  
07   $db_user $_SERVER['DB_USER'];
08   $db_pass $_SERVER['DB_PASS'];
09   $db_host 'localhost';
10  
11   if ($_sess_db = mysql_connect($db_host$db_user$db_pass))
12   {
13     return mysql_select_db('sessions'$_sess_db);
14   }
15  
16   return FALSE;
17 }
18  
19 function _close()
20 {
21   global $_sess_db;
22  
23   return mysql_close($_sess_db);
24 }
25  
26 function _read($id)
27 {
28   global $_sess_db;
29  
30   $id = mysql_real_escape_string($id);
31  
32   $sql = "SELECT data
33           FROM   sessions
34           WHERE  id = '$id'";
35  
36   if ($result = mysql_query($sql$_sess_db))
37   {
38     if (mysql_num_rows($result))
39     {
40       $record = mysql_fetch_assoc($result);
41  
42       return $record['data'];
43     }
44   }
45  
46   return '';
47 }
48  
49 function _write($id$data)
50 {
51   global $_sess_db;
52  
53   $access = time();
54  
55   $id = mysql_real_escape_string($id);
56   $access = mysql_real_escape_string($access);
57   $data = mysql_real_escape_string($data);
58  
59   $sql = "REPLACE
60           INTO    sessions
61           VALUES  ('$id''$access''$data')";
62  
63   return mysql_query($sql$_sess_db);
64 }
65  
66 function _destroy($id)
67 {
68   global $_sess_db;
69  
70   $id = mysql_real_escape_string($id);
71  
72   $sql = "DELETE
73           FROM   sessions
74           WHERE id = '$id'";
75  
76   return mysql_query($sql$_sess_db);
77 }
78  
79 function _clean($max)
80 {
81   global $_sess_db;
82  
83   $old = time() - $max;
84   $old = mysql_real_escape_string($old);
85  
86   $sql = "DELETE
87           FROM   sessions
88           WHERE  access < '$old'";
89  
90   return mysql_query($sql$_sess_db);
91 }
92  
93 ?>

你必须要在session_start( )之前调用session_set_save_handler( )函数,但你可以在任何地方对这些函数本身进行定义。

这个流程的漂亮之处在于你无须对代码进行编辑或变化使用会话的方式。$_SESSION依然存在,行为依旧,还是由PHP来产生与传递会识标识,对有关会话的配置变更同样还会生效。所有你需要做的只是调用这一个函数(同时建立由它指定的所有函数),PHP就会照顾余下的事情。

PHP安全编程:更优的会话数据安全 更好地防范session暴露(转)的更多相关文章

  1. 编程思想转换&体验Lambda的更优写法和Lambda标准格式

    编程思想转换做什么,而不是怎么做 我们真的希望创建一个匿名内部类对象吗?不,我们只是为了做这件事情而不得不创建一个对象. 我们真正希望做的事情是:将run方法体内的代码传递给Thread类知晓. 传递 ...

  2. PHP日志扩展 SeasLog-1.6.8, 性能更优

    SeasLog-1.6.8 发布了,性能更优. 改进日志: 1.6.8: 优化内存使用和性能,修复已知Bug. - Fixed issue #97 PHP5.* Cached Block. - Fix ...

  3. IntelliJ IDEA 2019.2最新解读:性能更好,体验更优,细节处理更完美!

    idea 2019.2 准备 idea 2019.2正式版是在2019年7月24号发布的,本篇文章,我将根据官方博客以及自己的理解来进行说明,总体就是:性能更好,体验更优,细节处理更完美! 支持jdk ...

  4. 体验Lambda的更优写法和Lambda标准格式

    体验Lambda的更优写法 借助Java8的全新语法,上述Runnable接口的匿名内部类写法可以通过更简单的Lambda表达式达到等效: public class Lambda02 { public ...

  5. 取代 Mybatis Generator,这款代码生成神器配置更简单,开发效率更高!

    作为一名 Java 后端开发,日常工作中免不了要生成数据库表对应的持久化对象 PO,操作数据库的接口 DAO,以及 CRUD 的 XML,也就是 mapper. Mybatis Generator 是 ...

  6. JavaWeb(二)会话管理之细说cookie与session

    前言 前面花了几篇博客介绍了Servlet,讲的非常的详细.这一篇给大家介绍一下cookie和session. 一.会话概述 1.1.什么是会话? 会话可简单理解为:用户开一个浏览器,点击多个超链接, ...

  7. 会话技术、Cookie技术与Session技术

    一.会话技术  1. 存储客户端状态 会话技术是帮助服务器记住客户端状态(区分客户端)的.  2. 会话技术 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,称为一次会话.会话技术就是记录这 ...

  8. MT【272】更大的视野,更好的思路.

    已知$f(x)=\sum\limits_{k=1}^{2017}\dfrac{\cos kx}{\cos^k x},$则$f(\dfrac{\pi}{2018})=$_____ 分析:设$g(x)=\ ...

  9. Java第三阶段学习(十三、会话技术、Cookie技术与Session技术)

    一.会话技术  1. 存储客户端状态 会话技术是帮助服务器记住客户端状态(区分客户端)的.  2. 会话技术 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,称为一次会话.会话技术就是记录这 ...

随机推荐

  1. Java学习----方法的覆盖

    方法的覆盖:子类继承父类,子类重写父类的同名方法. 覆盖的原则: 1. 方法的参数必须跟父类保持一致 2. 子类方法的修饰符的范围必须大于等于父类方法同名的修饰符(public > privat ...

  2. SQL UNION 和 UNION ALL 操作符

    SQL UNION 和 UNION ALL 操作符 SQL Full Join SQL Select Into SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结 ...

  3. 网页main中左边固定宽度,右边自适应。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 微信开放平台获取component_verify_ticket

    官方文档说明: 在公众号第三方平台创建审核通过后,微信服务器会向其“授权事件接收URL”每隔10分钟定时推送component_verify_ticket.第三方平台方在收到ticket推送后也需进行 ...

  5. bootstrap日期时间插件datetimepicker

    <!DOCTYPE HTML> 02 <html> 03   <head> 04     <link href="http://netdna.boo ...

  6. 在Linux终端执行clear或top命令时出现:'xterm': unknown terminal type

    在Linux终端执行clear或top命令时出现:'xterm': unknown terminal type的错误. 例如: [root@localhost phpmyadmin]# clear ' ...

  7. web一点小结

    1, AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法. AJAX ...

  8. WWDC2014之App Extensions学习笔记

    一.关于App Extensions extension是iOS8新开放的一种对几个固定系统区域的扩展机制,它可以在一定程度上弥补iOS的沙盒机制对应用间通信的限制. extension的出现,为用户 ...

  9. ASP.NET MVC 定义JsonpResult实现跨域请求

    1:原理 在js中,XMLHttpRequest是不能请求不同域的数据,但是script标签却可以,所以可以用script标签实现跨域请求.具体是定义一个函数,例如jsonp1234,请求不同域的ur ...

  10. Unity各平台路径总结

    路径是Unity开发中令人头疼的一个问题,根据我的开发经验,现将开发中遇到的路径问题总结如下: 1. 如何读取Application.streamingAssetsPath下的文件? Edit.iOS ...