-->

PHP Session Class and Use / Secure Logged In Page

2020-08-04 09:51发布

问题:

this may seem like a noob question but I've been searching for days and learning about session security, avoiding all security flaws normally found in websites, and initiating sessions that work the way I want them to (the typical such as x amount of time logged out or logging in from another location or etc).

All I'm after is getting my sessions to work, and getting them to work securely. Without further ado, I have a class that I include for the session

/* This SessionManager starts starts the php session (regardless of which handler is set) and secures it by locking down the cookie, restricting the session to a specific host and browser, and regenerating the ID.
*/

class SessionManager
{
/**
 * AOL users may switch IP addresses from one proxy to another.
 *
 * @link http://webmaster.info.aol.com/proxyinfo.html
 * @var array
 */
protected $aolProxies = array('195.93.', '205.188', '198.81.', '207.200', '202.67.', '64.12.9');

/**
 * This function starts, validates and secures a session.
 *
 * @param string $name The name of the session.
 * @param int $limit Expiration date of the session cookie, 0 for session only
 * @param string $path Used to restrict where the browser sends the cookie
 * @param string $domain Used to allow subdomains access to the cookie
 * @param bool $secure If true the browser only sends the cookie over https
 */
static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
    // Set the cookie name
    session_name($name . '_Session');

    // Set SSL level
    $https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);

    // Set session cookie options
    session_set_cookie_params($limit, $path, $domain, $https, true);
    session_start();

    // Make sure the session hasn't expired, and destroy it if it has
    if(self::validateSession())
    {
        // Check to see if the session is new or a hijacking attempt
        if(!self::preventHijacking())
        {
            // Reset session data and regenerate id
            $_SESSION = array();
            $_SESSION['IPaddress'] = isset($_SERVER['HTTP_X_FORWARDED_FOR'])
                        ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
            $_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
            self::regenerateSession();

        // Give a 5% chance of the session id changing on any request
        }elseif(rand(1, 100) <= 5){
            self::regenerateSession();
        }
    }else{
        $_SESSION = array();
        session_destroy();
        session_start();
    }
}

/**
 * This function regenerates a new ID and invalidates the old session. This should be called whenever permission
 * levels for a user change.
 *
 */
static function regenerateSession()
{
    // If this session is obsolete it means there already is a new id
    if(isset($_SESSION['OBSOLETE']))
        return;

    // Set current session to expire in 10 seconds
    $_SESSION['OBSOLETE'] = true;
    $_SESSION['EXPIRES'] = time() + 10;

    // Create new session without destroying the old one
    session_regenerate_id(false);

    // Grab current session ID and close both sessions to allow other scripts to use them
    $newSession = session_id();
    session_write_close();

    // Set session ID to the new one, and start it back up again
    session_id($newSession);
    session_start();

    // Now we unset the obsolete and expiration values for the session we want to keep
    unset($_SESSION['OBSOLETE']);
    unset($_SESSION['EXPIRES']);
}

/**
 * This function is used to see if a session has expired or not.
 *
 * @return bool
 */
static protected function validateSession()
{
    if( isset($_SESSION['OBSOLETE']) && !isset($_SESSION['EXPIRES']) )
        return false;

    if(isset($_SESSION['EXPIRES']) && $_SESSION['EXPIRES'] < time())
        return false;

    return true;
}

/**
 * This function checks to make sure a session exists and is coming from the proper host. On new visits and hacking
 * attempts this function will return false.
 *
 * @return bool
 */
static protected function preventHijacking()
{
    if(!isset($_SESSION['IPaddress']) || !isset($_SESSION['userAgent']))
        return false;


    if( $_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT']
        && !( strpos($_SESSION['userAgent'], ÔTridentÕ) !== false
            && strpos($_SERVER['HTTP_USER_AGENT'], ÔTridentÕ) !== false))
    {
        return false;
    }

    $sessionIpSegment = substr($_SESSION['IPaddress'], 0, 7);

    $remoteIpHeader = isset($_SERVER['HTTP_X_FORWARDED_FOR'])
        ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];

    $remoteIpSegment = substr($remoteIpHeader, 0, 7);

    if($_SESSION['IPaddress'] != $remoteIpHeader
        && !(in_array($sessionIpSegment, $this->aolProxies) && in_array($remoteIpSegment, $this->aolProxies)))
    {
        return false;
    }

    if( $_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT'])
        return false;

    return true;
}
}

So this is my class with several functions. It's straight forward. Below is how I implement it. (By the way, credit to this class goes to Team Treehouse and some other guy, so I didn't write it.)

Below, I have a login page and if the credentials are correct, I supposedly start the session:

// Earlier in the php I call it
include '/../session/session.php';

// 1. Check if the email exists (1 it does, 0 it doesn't)
    if ($emailFree == '1') {

            // Fetching login data
            $user->get_user($email);
            $pwStored = $user->password;
            $exStored = $user->exist;

            // 2. Check if they're activated
            if($exStored == '1') {

                // Encrypted input password
                $salt = generateSalt($email);
                $pwInput = generateHash($salt, $passw);

                // 3. Check if passwords match
                if($pwInput == $pwStored) {

                        SessionManager::sessionStart('awesomeWebsite');

                        header("Location: ../index.php");

                }

            }

            else {

                header("Location: ../index.php");

            }

    } 

    else {

If the credentials are correct, then it redirects to the index page, where I have an if statement to check if the session exists, if so then the user gains access to the "secure" page.

include 'session/session.php';

session_start();
$sessionName = session_name();

if(isset($_SESSION['stalker']) && !empty($_SESSION['awesomeWebsite'])) {
    echo 'Junk, session initiated';
    echo $sessionName;
}
else if (!isset($_SESSION['stalker']) && empty($_SESSION['awesomeWebsite'])) {
    echo "NO session";
    echo $sessionName;
}
else {
    include 'login.php';
}

So the problem I'm having is that upon entering the correct credentials, the function on the index page doesn't find a session. I see some people adding session variables then checking them, should I add a session variable in my class file when the session is created, then check to see if that session variable exists in the index page?

I know this is long and not the most presentable, but thanks for all the help and suggestions anyone can provide!

回答1:

So I have the sessions working now, here's the code:

Login.php (logic)

if({
SessionManager::sessionStart('website');                
$_SESSION['logged_in'] = 'true';
header("Location: ../index.php");

Index.php

SessionManager::sessionStart('website');

$logged_in = $_SESSION['logged_in'];

if(isset($logged_in) && !empty($logged_in)) {
    echo 'Junk, session initiated';
    echo "<br>" . $logged_in;
}
else if (isset($logged_in) && empty($logged_in)) {
    echo "NO session";
    echo "<br>" . $logged_in;
}
else {...}

Seems to work now, I guess I just needed to declare a session variable then add "SessionManager::sessionStart('website');" to the top of the index page to call my class for the session logic.