Ana Ban
Ana Ban

Reputation: 1405

How to properly manage PHP sessions

I need to work with sessions only to maintain form input from edit.php(1) to post.php(2) to edit.php(3) if the input validation failed on save_post, so that my users don't have to re-fill the form at edit.php(3) with their previous entries at edit.php(1) since post.php(2) does not re-post to edit.php(3). There are a number of ways to transient data through this tunnel:

  1. WordPress uses the querystring for its messages - aside from the common cons of querystrings for my purpose, I did not go this way as my $_POST vars may be too much for the querystring
  2. the Transient API - nope, not this one either for (remotely possible) collision reasons
  3. modify edit.php and post.php directly - unsustainable especially over updates. I could look for hooks for this if I can't find anything else
  4. sessions,

among others.

I will not use sessions for login (since I'm using WordPress, I'll let WordPress take care of that.) From scouring the web, I inserted the following in my functions.php:

/*
 * manage sessions
 */
// http://wblinks.com/notes/secure-session-management-tips
// http://devondev.com/2012/02/03/using-the-php-session-in-wordpress/
// http://en.wikipedia.org/wiki/Session_fixation
// http://www.php.net/manual/en/function.session-regenerate-id.php
if (is_admin()) add_action('init', 'empl_sesh_start', 1);
add_action('wp_login', 'empl_sesh_cleanup');
add_action('wp_logout', 'empl_sesh_cleanup');
function empl_sesh_start() {
    session_start();
    // check if loaded session is server-generated
    if (!isset($_SESSION['IS_SERVER_TRUSTED']))
        session_regenerate_id(true); // if not, regenerate id and clean-up previous session files
    // regenerate id for every request
    session_regenerate_id();
    $_SESSION['IS_SERVER_TRUSTED'] = true; // set flag
}
// cleanup
function empl_sesh_cleanup() {
    session_start(); // needed for the rest of this function to work
    $_SESSION = array(); // cleanup session variables
    session_regenerate_id(true); // regenerate id and clean-up previous session files
    session_destroy();
}

I just need to know if I got it right. I'm particularly concerned with

  1. are the order and calls to the session statements correct?
  2. are they necessary (in an effort to make the session less vulnerable as pointed out by the online articles)?

I'm also concerned with what I read about unsetting cookies and their complexities - do I need to do that? I don't use any cookies, I just use two session variables:

// persist form vars to next load
$_SESSION['empl_form_inputs'][] = $_POST['empl_age'];
    // more similar code here...
$_SESSION['empl_form_inputs'][] = $_POST['empl_id'];

// persist message array to next load
$_SESSION['empl_messages'] = $empl_messages;

I posted this here instead of at wordpress.stackexchange.com as (I think) this is not really a WordPress question, but more of a PHP Session best practice.


RESOLUTION: I ended up abandoning the whole session caboodle and implemented collision-addressed (at least for my use case) transients with a 1 second expiration. thanks @Robbie

Upvotes: 0

Views: 744

Answers (1)

Robbie
Robbie

Reputation: 17710

You shouldn't need sessions for posting from a form, not even in wordpress.

Your script / plugin should read.

  • Create values with default values
  • Create "empty" error conditions
  • If Post
    • Populate "default" values from POST
    • Sanitize values
    • Validate Values
    • If valid
      • Create action (e.g. put the values in DB)
      • Redirect to another page showing result/scucess message (prevents back button failure)
    • If not valid
      • Poulate error conditions
  • Display form using values and error conditions.

You'd use a session if you were using a wizard (multi-page form) approach. This way the form alsways shows what the user enters and errors.


However, to answer your question, your addactions() are probably what you want, but the functions are agressive.

  • The init looks fine - ish (note comment on regenerating ID below)
  • The cleanup is risky as you will obliterate any other plugins that use sessions. Just delete your entries ( $_SESSION['empl_form_inputs'] = array(); ) and move on
  • If you mess about with the sesson ID like that, you're going to totally screw over any other plugins that use sessions.
  • For "security" keep the same session ID, but track where it comes from and give it a time-out. So if session_id() = "ABC" has not been used for 10 minutes, or comes from a different user agent, then ignore those values you had and start again.

Example of time-out:

if ($_SESSION['empl_form_expires'] > time()) {  // Also add user agent chack or something
    $_SESSION['empl_form_inputs'] = array();  // Clear values
} else {
    $_SESSION['empl_form_expires'] = time() + 600;  // Keep the time running
}

Upvotes: 2

Related Questions