当你关注于防止源码的暴露时,你的会话数据只同样存在着风险。在默认情况下,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. overflow第一次觉得你有点可恶

    今天用css做下拉菜单,因为不需要做手机自适应,再手机里看起来工整一点就行,可是列表中最后一个li的宽度撑开了父div,导致看起来很糟糕,所以给父元素加overflow:hidden:但是下拉列表也被 ...

  2. Jquery中index()问题

    对于Jquery中的index()问题,很多人会说这个很简单的,并不是一个非常困难的方法.笔者开始的时候也是这样子认为的,但是今天遇到一个index的问题,让我忙了一个晚上都没有解决,最后还是使用co ...

  3. highcharts实例教程二:结合php与mysql生成饼图

    上回我们分析了用highcharts结合php和mysql生成折线图的实例,这次我们以技术cto网站搜索引擎流量为例利用highcharts生成饼图. 饼图通常用在我们需要直观地显示各个部分所占的比例 ...

  4. windows server 2008 asp连接数据库sql2000失败

    由于服务器现在的服务器已不能承受了,需要替换服务器并把window2003升级为window2008,把所有数据都平移过来.平移完后遇到ASP总是不能连接上sql2000,这让我非常郁闷,处理了好几个 ...

  5. 项目任务管理(TaskMgr)设计篇

    为什么使用void FilllXX(TypeA pParm1, TypeB pParm2) 应用场景色:void FillXX的好处是可以不用关心实例情况:如果在方法体中需要一个实例,而方法体只知道基 ...

  6. IOS 点击空白处隐藏键盘的几种方法

    IOS 点击空白处隐藏键盘的几种方法     IOS7 点击空白处隐藏键盘的几种方法   IOS开发中经常要用到输入框,默认情况下点击输入框就会弹出键盘,但是必须要实现输入框return的委托方法才能 ...

  7. 应用Oracle(用户创建和授权)

    使用oracle命令创建用户,并授权. 系统管理员身份登录 cmd中, sqlplus / as sysdba 若登录失败,则 sqlplus system/[数据库创建时指定密码] as sysdb ...

  8. Oracle开始从Java运行时中移除JAR包

    早在2012年8月,在Java平台首席架构师Mark Reinhold宣布模块化项目Jigsaw之后不久,JEP 162这一题为“准备模块化”的提案就指出,在Jigsaw项目中为模块化系统开发的代码不 ...

  9. 关于如何在BCB中使用CodeGuard

    作者:深圳虫 来自:深圳虫网本文来自http://www.szbug.com/disparticle.aspID=4 一. 为什么写这篇东西自己在使用BCB5写一些程序时需要检查很多东西,例如内存泄漏 ...

  10. 【转】轻量级文本编辑器,Notepad最佳替代品:Notepad++--不错

    原文网址:http://www.crifan.com/files/doc/docbook/rec_soft_npp/release/htmls/npp_function_column_mode.htm ...