Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8218
  • 博文数量: 4
  • 博客积分: 146
  • 博客等级: 入伍新兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-10 04:47
文章分类

全部博文(4)

文章存档

2012年(4)

我的朋友
最近访客

分类: 系统运维

2012-10-19 04:41:37


Session Management Session management is a mechanism for maintaining and sharing the state of variables (called session variables) for every participating program in a web project. These variables are not lost when you go offsite and return. This is one of the key ingredients of a web-based shopping cart used in e-commerce. The server can maintain a relationship with a browser session by sending and receiving information packets called cookies. A cookie is simply a name/value pair of data which contains other attributes such as the target URL (server name and path) and expiration timestamp. In session management using cookies, when a browser first contacts a web server, the server sends a cookie called the session id which is then stored in the browser. The value of the session id is some fixed-length "random" sequence of hex digits which the server uses to identify the browser connection and associate some persistent information. When the browser makes a subsequent contact to the server so that the cookie's URL matches the server URL, the cookie is sent to the server. Session handling is built-in to Php using cookies whose name is PHPSESSID. As mentioned above, the cookie is originally sent from the server to the browser and then subsequently sent back to the server for all future contacts to that site during the current browser session. The default lifetime for a PHPSESSID cookie is the browser session, i.e., as long as the browser remains open. Php session management A Php program begins session management by calling the function: session_start(); From then on, the $_SESSION array can be used to keep track of any number of variables via user-determined keys. The session_start function must be called prior to the echoing of any HTML code. Any file in which this is used must start with very first characters in the file, i.e., no other characters (even whitespace) prior to this. Once a session has been established and we set $_SESSION['name'] = /* some serializable value */; then $_SESSION['name'] is available to all other participating scripts. To invalidate a session variable: unset($_SESSION['name']); To invalidate all session variables: session_destroy(); Content of the session files For a better understanding, look at the session files themselves. They are stored in the temporary directory specified by session.save_path in the Php init file. In Linux, these files are owned by the Apache user and so you have to become root to read them. The session files are of the form: sess_ like this: sess_71c3cf38b232720002c25fd7919066e5. The content is a string created by serializing the $_SESSION array with the Php serialize function. For example, serialize( array( "xx" => -15, "yy" => array(3,4) ) ) = "a:2:{s:2:"xx";i:-15;s:2:"yy";a:2:{i:0;i:3;i:1;i:4;}}" A Php program which uses sessions obtains the stored values by de-serializing the session using the Php unserialize function. Controlling the path of the session By default, the path of the PHPSESSID cookie is "/", meaning usually that the cookie will be sent to anywhere within the domain. If you want to restrict the path to the directory in which these scripts are defined, you need to use the session_set_cookie_params function prior to the first session_start() call when the cookie is sent to the browser. For example, this call makes the session valid only for scripts within the current directory: session_set_cookie_params(0, dirname(__FILE__) . "/"); Here we're using the built-in Php special __FILE__ constant which always gives the absolute path of the file in which it's used. Using $_SESSION with a KEY The $_SESSION superglobal variable, like others, is an associative array, which means that we can store and retrieve information in it's entries, like: $_SESSION['valid'] As you will see in our examples, the $_SESSION array is used in a more complicated fashion. Instead of using it in this "one-dimensional" manner, we use it in a two-dimensional manner by creating the array: $_SESSION[KEY][...] = ... The value of KEY is a constant defined somewhere and made available to all scripts which use sessions. The function of this KEY usage is to separate your application's session from other sessions on the same server. Suppose you were to omit the usage of KEY and suppose in one application you had, for some reason, set $_SESSION['valid'] = 1 Now suppose you enter a separate application on the same server which uses the same validation strategy and tests for validated access by doing: if ( isset($_SESSION['valid']) ) { // I can access some protected resource } In effect, you have achieved priviledged status in the former application and exported this status in the latter application. One might refer to this effect as bleed-over. It is a consequence of the global nature of the $_SESSION variable. You will be secure in avoiding bleed-over if, like a password, KEY is both
  • secret
  • not likely to be reproduced
The good news is that, unlike a password, you do not need to remember it. A Session class Because of the syntactic complexity of using session variable of the form:
$_SESSION[KEY]['param']
it is easier and less error prone to wrap the read/write operations as getter/setter operations in a dedicated class. In particular, throughout our web development, we will make exensive use of the included file:
include/Session.php
session_start();   define( "SECRET", "-set-this-to-make-sessions-secure-" ); define( "HASH", md5(dirname(__FILE__) . SECRET) ); define( "KEY", "sess_" . HASH );   class Session { public function __set($name,$value) { $_SESSION[KEY][$name] = $value; } public function & __get($name) { return $_SESSION[KEY][$name]; } public function __toString() { $sess = $_SESSION[KEY]; foreach ($sess as $key => $value) { if (!isset($value)) unset($sess[$key]); } return print_r($sess,true); } public function __isset($name) { return isset($_SESSION[KEY][$name]); } public function __unset($name) { unset($_SESSION[KEY][$name]); } public function unsetAll() { unset($_SESSION[KEY]); } }
The session KEY uses the md5 hash of the full path to the application's include directory plus a chosen SECRET value. With this combination we are ensured that:
  1. the KEY will vary from one application to another
  2. if SECRET is an unknown value, another user cannot "guess" the KEY even when the include directory path is know.
Sample Scripts This demo web app uses the template from the Website Template document. Three view scripts session-demo.php form1.php, form2.php, form3.php along with additional so-called handler files handler-sess-set.php, handler-sess-unset.php, and handler-sess-clear.php offer a demonstration of session behavior. A modified version of the Session class is used to illustrate the behavior of the member functions:
include/Session.php (click to show)
In this modified version, member function activations are reported whenever this constant is defined:
define("DEBUG",1)
session-demo.php This illustrates the "magic methods" used in Php classes. In particular the magic methods establish this relationship between usage and underlying behavior:
$session->var = 17; // __set: $_SESSION[KEY]['var'] = 17   $value = $session->var; // __get: $value =& $_SESSION[KEY]['var'];   if (isset($session->var)) // __isset: if (isset($_SESSION[KEY]['var']))   unset($session->var) // __unset: unset($_SESSION[KEY]['var']);   echo "$session"; // __toString
Here is the code:
session-demo.php
require_once "include/Session.php"; $session = new Session(); define("DEBUG",1); ?> ...  

Session Demo

  $session->x = 5;   echo $session->x, "\n";   echo $session->y, "\n";   echo "$session\n";   if (isset($session->x)) echo "yes\n"; else echo "no\n"; if (isset($session->y)) echo "yes\n"; else echo "no\n";   unset($session->x);   echo "$session\n";   print_r($_SESSION);   ?>  
The most unusual of these methods is __get which returns the variable by reference. The implication is that, when it is used in the statement
$value = $session->some_var;
the variables $value and $session->some_var are identical. In particular this is necessary to make a statement like this, which auto-generates and array, work:
$session->some_var[] = "foo";
One strange side-effect of return-by-reference in __get is that attempting to use an undefined session key will make the key appear, associated with the null value. In our test program we use the undefined "y" session key:
echo $session->y, "\n";
Later we confirm that this session variable is unset:
echo $session->y, "\n"; if (isset($session->y)) echo "yes\n"; else echo "no\n";
At the end, however, we see the "y" session key turn up in:
print_r($_SESSION);
form1.php This first script presents a standard reentrant form which holds its values by resetting them based on the incoming query parameters. This simple stateless form script has the "problem" that when we leave the script and return, the state values are lost. Here is the script code:
form1.php
require_once "include/items.php";   $params = (object) $_REQUEST;   if (isset($params->button)) { $choices->sel1[$params->sel1] = "selected"; } ?> ...  

Form1

 
params:  print_r($params); ?>
choices:  print_r($choices) ?>

 
tf1: echo htmlspecialchars($params->tf1) ?>" />
sel1:
 
All form scripts include this file:
include/items.php
$items = array( 1=>"AA", "BB", "CC", "DD", "EE", "FF", "GG" );
The array indices will be used as the underlying selection option values and the array values will be the option labels. It is usually a good idea to avoid having a "false" option value for "real" option choices; therefore we use a 1-based array instead of the default 0-based array. form2.php The form2.php and form3.php scripts are variations in which we use sessions. The form2.php script stores parameter values as session values when the internal form has been activated is set. The code expresses the idiosyncratic way to do so by resetting the session value only for a reentrant activation. By doing so, we can remember the values throughout the session, thereby making the form elements session-stable.
form2.php
require_once "include/Session.php"; $session = new Session();   require_once "include/items.php";   $params = (object) $_REQUEST;   if (isset($params->button)) { $session->tf2 = $params->tf2; $session->sel2 = $params->sel2; $message = "Set session keys: tf2, sel2";   //header("location: " . $_SERVER['PHP_SELF']); exit(); }   if (isset($session->tf2)) { $tf2 = $session->tf2; }   if (isset($session->sel2)) { $choices->sel2[$session->sel2] = "selected"; } ?> ...  

Form2

 
params:  print_r($params); ?>
 if (isset($choices)):
 echo "choices: ";
 print_r($choices);
endif ?>
session:  echo $session ?>

 
tf2: echo htmlspecialchars($tf2) ?>" />
sel2:
  echo $message?>  
Since the form element values are held in the session, there is no need to proceed through the form when they are set from the parameters. In some cases it is useful to simply redirect to the initial activation. We can do so by uncommenting the statements:
header("location: " . $_SERVER['PHP_SELF']); exit();
The header function places information into the server's response sent back to the browser which causes the browser to redirect to the specified location, i.e., redirect to the script provided by the location information. This usage of the header function makes the browser "redirect to the script itself" which means that we're forcing the browser to reload. The exit function call is used to stop executing code within this current script which would be ignored anyway because the browser is being redirected. The issue now is that, when the redirection is in place, the $message is no longer passed from the top contoller part to the bottom view part. In the next section we will illustrate a mechanism for sending information such as this across the redirection. form3.php This calls an external handler script, session-from-query.php, whose sole job is to set the session values from the query parameters and redirect back to the original script. The code is this:
form3.php
require_once "include/Session.php"; $session = new Session(); require_once "include/items.php";   if (isset($session->sel3)) { $choices->sel3[$session->sel3] = "selected"; }   if (isset($session->tf3)) { $tf3 = $session->tf3; }   $message = $session->message; unset($session->message); ?> ...  

Form3

 
session:  echo $session ?>

 
tf3: echo htmlspecialchars($tf3) ?>" />
sel3:
 
 
 
  echo $message?>  

There are three forms in the form3.php script. Each of them calls one of the three corresponding external "handler" scripts which all redirect back to form3.php.

handler-sess-set.php
require_once "include/Session.php"; $session = new Session();   // set session values from query parameters foreach ($_REQUEST as $key => $value) { $session->__set($key,$value); }   $session->message = "set keys: " . join(", ", array_keys($_REQUEST));   header( "location: " . $_SERVER['HTTP_REFERER'] );
handler-sess-unset.php
require_once "include/Session.php"; $session = new Session();   $params = (object) $_REQUEST;   foreach ($params->key2unset as $key) { $session->__unset($key); }   $session->message = "unset keys: " . join(", ", $params->key2unset);   header( "location: " . $_SERVER['HTTP_REFERER'] );
handler-sess-clear.php
require_once "include/Session.php"; $session = new Session();   $session->unsetAll();   $session->message = "unset all keys";   header( "location: " . $_SERVER['HTTP_REFERER'] );
We term these handler scripts because they do not in themselves generate a view; they simply perform some action and then redirect somewhere else. The special server variable $_SERVER['HTTP_REFERER'] provides the full URL of the caller. The redirection, after peforming its actions effectively goes back to form3.php via the statement:
header("location: " . $_SERVER['HTTP_REFERER']);
An important idea illustrated in these script is the use of so-called flash memory which is "one-time" session usage variables. The mechanism is that, prior to redirection back, we set a message:
$session->message = /* some message */;
Back in form3.php we retrieve this message in the controller section:
$message = $session->message; unset($session->message);
and then drop it into the view section below as we did in form2.php:
echo $message?>
The read/unset treatment in the controller section ensures that the message will be displayed only once. If we subsequently refresh the page or access form3.php from the outside, the message is gone, thus establishing its "flash" behavior.
阅读(403) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~