Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session will live for only 24 minutes no matter what #25

Closed
Tklaversma opened this issue Aug 18, 2014 · 16 comments
Closed

Session will live for only 24 minutes no matter what #25

Tklaversma opened this issue Aug 18, 2014 · 16 comments

Comments

@Tklaversma
Copy link

Hi Eric,

First of all, amazing plugin!

My problem.
It seems to me that no matter what, the sessions will only live for 24 minutes. If I read a session variable after it has been set 10 minutes ago, the expiration should reset to 24 minutes, right?

"By default, session variables will live for 24 minutes from the last time they were accessed - either read or write."

I use the following code to set an variable on page load

$wp_sessions = WP_Session::get_instance();
$wp_sessions['id'] = $id;

and use the following to read. If session doesn't exist, I redirect to the login page.

$wp_sessions = WP_Session::get_instance();
if ( isset( $wp_sessions['id'] ) ) {
    return true;
}
wp_redirect( 'http://www.example.com/login/', 302 );
exit;

Hope you can help me out.

Regards,
TK

@ghost
Copy link

ghost commented Sep 3, 2014

Same issue here.

add_filter( 'wp_session_expiration', function() { return 60 * 60; } );

Doesn't help

@ericmann
Copy link
Owner

ericmann commented Sep 5, 2014

Sorry, the language there is confusing. Sessions will live for 30 minutes, but their expiration is reset after 24 minutes using the expiration variant. Setting the wp_session_expiration filter will make them live longer, but the variant is still set to 24 minutes.

Essentially, for the first 24 minutes after being created, nothing will change unless you tell it to. After those 24 minutes expire, the expiration is updated so the session stays alive. If you pass the 30 minute expiration window, then the session expires automatically.

@ericmann ericmann closed this as completed Sep 5, 2014
@ghost
Copy link

ghost commented Sep 5, 2014

I need my sessions to live for days, without user having to login in 24-30 minute window.

I've debugger plugin extensively and no matter where i set it,

apply_filters( 'wp_session_expiration_variant', 24 * 60 )

always returns default value

https://github.com/ericmann/wp-session-manager/blob/master/class-wp-session.php#L116

@ericmann
Copy link
Owner

ericmann commented Sep 5, 2014

apply_filters() applies a filter to a value. You want add_filter(). More specifically:

add_filter( 'wp_session_expiration_variant', function() { return 24 * 60 * 60; } );

@ghost
Copy link

ghost commented Sep 5, 2014

Did that.
Doesn't work. It still lives only for 30 min.

@ericmann
Copy link
Owner

ericmann commented Sep 5, 2014

Sorry, hold on.

There are two things going on here. An expiration (which you want to live for a day) and an expiration variant (a timeout to prevent updating the session too quickly). By default, the expiration is 24 minutes. To make it 24 hours, use:

add_filter( 'wp_session_expiration', function() { return 24 * 60 * 60; } );

To make the variant wait until, say, 20 hours before refreshing the session, use:

add_filter( 'wp_session_expiration_variant', function() { return 20 * 60 * 60; } );

@ghost
Copy link

ghost commented Sep 5, 2014

I understand the difference.
Did that.
Doesn't work.
Cookie set to expire in 24-30 min.

@privard
Copy link

privard commented Nov 20, 2014

I have to agree with artyomboyko. I tried applying both the wp_session_expiration_variant and wp_session_expiration filters but WP_Session::$expires and WP_Session::$exp_variant are stuck at 24-30 minutes. It looks like the filters are not being picked up for some reason.

In my functions.php

add_filter('wp_session_expiration', 'extend_session_expiration', 10); 
function extend_session_expiration($value) {
  return 48 * 60 * 60;
}

add_filter('wp_session_expiration_variant', 'extend_session_expiration_variant', 10);
function extend_session_expiration_variant($value) {
  return 24 * 60 * 60;
}

Yet, in WP_Session::set_expiration, if I output the return value of the filters with

error_log((int) apply_filters( 'wp_session_expiration_variant', 24 * 60 ));
error_log((int) apply_filters( 'wp_session_expiration', 30 * 60 ));

I just get the default value in my logs

[20-Nov-2014 17:33:36 UTC] 1440
[20-Nov-2014 17:33:36 UTC] 1800

I checked everywhere else in my code just in case remove_filter was being called, but nothing seems to interfere with the filter. Any ideas?

@natebeaty
Copy link

natebeaty commented Jun 21, 2016

FWIW I have the same problem, no matter where I put:

// Set wp_session_expiration to 24 hours and wp_session_expiration_variant to 20 hours
add_filter('wp_session_expiration', function() { return 24 * 60 * 60; });
add_filter('wp_session_expiration_variant', function() { return 20 * 60 * 60; });

It has no effect on the expiration or expiration_variant.

@joelambert
Copy link

joelambert commented May 8, 2017

It's because the session is created in the plugin_loaded action which happens before any theme code can run. So adding the filters has no effect as the thing that runs the filters has already executed before your code can add them to the queue.

I worked around this by creating a small custom plugin that can apply the custom filters before the WP Session plugin initialises for the first time.

Add something like the following to a custom plugin file:

add_action('plugins_loaded', function () {
    add_filter('wp_session_expiration_variant', function () {
        return 20 * 60 * 60;
    });

    add_filter('wp_session_expiration', function () {
        return 24 * 60 * 60;
    });
}, 1);

@Tklaversma
Copy link
Author

It has been a while, but @joelambert his solution works. It would be nice if the plugin FAQ would also be updated on the WordPress plugin page (wordpress dot org/plugins/wp-session-manager/).

@VivekManglani
Copy link

@ericmann how do we handle this in 3.0?

@Tklaversma
Copy link
Author

Tklaversma commented Jan 31, 2018

First of all make a wrapper class, so that its easier to maintain your sessions:

<?php

namespace App\Sessions;

/**
 * Wrapper class for WP_Session that holds functionality to get, set and delete current sessions and sessiondata
 * and that adds the use of serialize() and unserialize().
 */
class SessionController
{
    /**
     * Get all sessions.
     *
     * @return array
     */
    public function get_sessions()
    {
        return $_SESSION;
    }

    /**
     * Get session by given key.
     *
     * @param string $key - Unique identifier of the session.
     *
     * @return bool|mixed
     */
    public function get($key)
    {
        return isset($_SESSION[$key]) ? unserialize($_SESSION[$key]) : false;
    }

    /**
     * Store data in a session with given key and value.
     *
     * @param string $key   - Unique identifier for the session.
     * @param mixed  $value - The value for the session.
     *
     * @return void
     */
    public function set($key, $value)
    {
        unset($_SESSION[$key]);
        $_SESSION[$key] = serialize($value);
    }

    /**
     * Delete session by given key.
     *
     * @param string $key - Unique identifier of the session.
     *
     * @return void
     */
    public function delete($key)
    {
        if ($_SESSION[$key]) {
            unset($_SESSION[$key]);
        }
    }

    /**
     * Remove all existing sessions.
     *
     * @param bool $deleteSpecials - Indicates whether or not to delete specials sessions as well.
     *
     * @return void
     */
    public function delete_all($deleteSpecials = false)
    {
        $specialKeys = [
            'LAST_ACTIVITY',
        ];

        if (count($_SESSION) > 0) {
            foreach ($_SESSION as $k => $v) {
                if ($deleteSpecials !== true) {
                    if (in_array($k, $specialKeys, true)) {
                        continue;
                    }
                }

                unset($_SESSION[$k]);
            }
        }

        if ($deleteSpecials === true) {
            $_SESSION = [];
        }
    }
}

Since 3.0 makes use of the default global session variable, we have to keep track of the expiration ourselfs.
What most people do, is set a session that keeps track of the last activity, which essentially does the same as wp_session_expire().

<?php

/**
 * Session expiration.
 *
 * Set the expiration time of our (WordPress) sessions to 1 hour.
 */
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > (60 * 60 * 1))) {
    session_unset();
    session_destroy();
    session_start();
}
$_SESSION['LAST_ACTIVITY'] = time();

I hope this is what you are looking for.

@ericmann
Copy link
Owner

Since we're using native session functionality, you can either:

  • Use PHP's native session lifetime configuration to tweak how long a session will live
  • Set a "last activity" time in the session and manually clear things up. Though I wouldn't recommend the use of a full wrapper class as outlined by @Tklaversma above. Instead:
function purge_stale_sessions() {
    if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > (60 * 60 * 1))) {
        session_unset();
        session_destroy(); // Purge stored session data
        session_start(); // Restart the session
    }
    $_SESSION['LAST_ACTIVITY'] = time();
}
add_action('wp_session_init', 'purge_stale_sessions');

@Tklaversma
Copy link
Author

Tklaversma commented Jan 31, 2018

@ericmann The foremost reason to use a wrapper class is that you can (and did 👎 ) change how the library works. When I updated to version 3.0 in the beginning, all I had to do is change my functions, which only took 2 min. Others have had problems since they used your code through their whole project and had to change it everywhere. No bad feelings, but not recommending without a valid reason makes no sense.

Besides the above, I do like your solution to hook on the wp_session_init()

@ericmann
Copy link
Owner

@Tklaversma Version 3.0 was not intended to be backwards compatible. This is why the major version incremented from 2.X to 3.X. That being said, community members have contributed a patch to the latest version (3.0.3) that brings back the global WP_Session object and allows you to still use the exact same code as you did with the older versions.

With this change, WP_Session is itself a wrapper class over the regular $_SESSION functionality. All of the other wp_session_{etc} functions remain and do the exact same thing they did before (which was mimic the standard Session functionality), they just now fall through to native Session functions and flag themselves as deprecated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants