保护会话
默认情况下,PHP 中的会话信息将被写入临时目录。考虑清单 5 中的表单,该表单将显示如何存储会话中的用户 ID 和帐户编号。
清单 5. 存储会话中的数据
以下为引用的内容: <?php session_start(); ?> <html> <head> <title>Storing session information</title> </head> <body> <?php if ($_POST['submit'] == 'Save') { $_SESSION['userName'] = $_POST['userName']; $_SESSION['accountNumber'] = $_POST['accountNumber']; } ?> <form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> <div><input type="hidden" name="token" value="<?php echo $token; ?>" /> <input type="text" name="userName" value="<?php echo(isset($_POST['userName']) ? $_POST['userName'] : ''); ?>" /> <br /> <input type="text" name="accountNumber" value="<?php echo(isset($_POST['accountNumber']) ? $_POST['accountNumber'] : ''); ?>" /> <br /> <input type="submit" value="Save" name="submit" /></div> </form> </body> </html> |
清单 6 显示了 /tmp 目录的内容。
清单 6. /tmp 目录中的会话文件
-rw------- 1 _www wheel 97 Aug 18 20:00 sess_9e4233f2cd7cae35866cd8b61d9fa42b
正如您所见,在输出时(参见清单 7),会话文件以非常易读的格式包含信息。由于该文件必须可由 Web 服务器用户读写,因此会话文件可能为共享服务器中的所有用户带来严重的问题。除您之外的某个人可以编写脚本来读取这些文件,因此可以尝试从会话中取出值。
清单 7. 会话文件的内容
userName|s:5:"ngood";accountNumber|s:9:"123456789";
您可以采取两项操作来保护会话数据。第一是把您放入会话中的所有内容加密。但是正因为加密数据并不意味着绝对安全,因此请慎重采用这种方法作为保护会话的惟一方式。备选方法是把会话数据存储在其他位置中,比方说数据库。您仍然必须确保锁定数据库,但是这种方法将解决两个问题:第一,它将把数据放到比共享文件系统更加安全的位置;第二,它将使您的应用程序可以更轻松地跨越多个 Web 服务器,同时共享会话可以跨越多个主机。
要实现自己的会话持久性,请参阅 PHP 中的session_set_save_handler()函数。使用它,您可以将会话信息存储在数据库中,也可以实现一个用于加密和解密所有数据的处理程序。清单 8 提供了实现的函数用法和函数骨架示例。您还可以在参考资料小节中查看如何使用数据库。
存储密码
不管是在数据库、会话、文件系统中,还是在任何其他表单中,无论如何密码都决不能存储为纯文本。处理密码的最佳方法是将其加密存储并相互比较加密的密码。虽然如此,在实践中人们仍然把密码存储到纯文本中。只要使用可以发送密码而非重置密码的 Web 站点,就意味着密码是存储在纯文本中或者可以获得用于解密的代码(如果加密的话)。即使是后者,也可以找到并使用解密代码。
清单 8.session_set_save_handler()函数示例
以下为引用的内容: function open($save_path, $session_name) { /* custom code */ return (true); } function close() { /* custom code */ return (true); } function read($id) { /* custom code */ return (true); } function write($id, $sess_data) { /* custom code */ return (true); } function destroy($id) { /* custom code */ return (true); } function gc($maxlifetime) { /* custom code */ return (true); } session_set_save_handler("open", "close", "read", "write", "destroy", "gc"); |