5

So I have a requirement that I'm getting close to stumped on how to complete in Drupal 8.

I'm going to attempt to simplify the requirements. I have two roles. They are essentially mutually exclusive. Let's call them "Internal" and "Client".

The request is to have Clients logged in for an indefinite period of time... let's call it years. Internal users need to be logged in for a short period of time, say 1 day, or even just the session. (Note: I didn't make these requirements, just coding them... haha)

My understanding of the Drupal login is that there are really two things controlling this... there is the cookie lifetime of a user, and the session lifetime (on the server). If I set the cookie lifetime to 1 week, but the session lifetime is 1 day, the user will essentially be logged out after 1 day, b/c their cookie will match a session that doesn't exist after a day... is that right?

So, I think I have to start with the upper limit. If I want my user to be logged in for 1 year, I need my server session to be 1 year. One of my questions is: what are the risks/downsides/etc to setting my server session to 1 year? Let's say my server gets 50k visits a month. What if it's not 1 year, and I want it at 2 years? I can't seem to find a definitive guide to what the upper limit of server session should be? It seems like there's a lot of factors that could clear out that session as well...

Ok, so the above is one question... assuming I can set the server session, how can I have the cookie lifetime visit based on user role? I'm getting to the point where it seems like it just might not be possible to vary this setting, and I might have to do some kind of route subscriber and custom cookies and whanot to detect the internal users, and log them out when I see they've been logged in too long...

Any help would be much appreciated...

2 Answers 2

2

I have achieved this goal in the past for Drupal 7 using a bit of custom code.

  1. Set the cookie lifetime and server session timeout to the larger of the 2 numbers, in your case I guess that's 2 years.
  2. Write a custom script (e.g. in drush) that will find stale sessions and delete them.

For item #2 for you that means it has to find the Internal users with a short lifetime and delete their session if the sessions.timestamp is beyond a limit. According to system.install, that column contains The Unix timestamp when this session last requested a page.

The limit of your sessions table depends on database server hardware, but my experience on a fairly large site is that you can have millions of sessions records and it's not a huge problem for performance. That said, I also found that user interaction followed a power-curve. 90% of users who committed and got engaged did so within the first day. 95% were within the first week and going out to 3 months got up to 98%. Saving the cookie data beyond that for what amounts to a rounding error is generally not super useful.

I found that trying to do a sql delete directly does not scale well. Instead, I wrote a loop that would find records to delete and then run individual delete queries with a condition WHERE sid = :sid so it was using a primary key. This had the greatest performance while having minimal impact. You can even run the select against a read-replica database to reduce the performance impact further. For my scenario, 1 class of users who had not been active in the last hour were logged out so that job ran every hour. The other class of users who got deleted after 3 months would be deleted in a job that ran overnight as it performed more operations and had more impact on server resources.

If you truly need to store session data for 2 years that's fine. However, you might consider if you can instead store the data in the cookie instead of in the session. That way your sessions table stays lightweight and you can still do tracking of the user inside the cookie. For example, if your goal is to track a channel that brought the user to the site you could simply store that channel information in their cookie instead of the $_SESSION. If you can avoid generating/keeping a session then the scalability problem goes away.

Beware that many spiders and bots generate significant traffic and are poorly behaved a it relates to sessions: they may discard cookies, effectively generating a new session for every page request if your app does that. You can either place a bot-blocking/caching network in front (like Cloudflare) or just plan to periodically analyze the sessions table and delete sessions from these bots based on something like IP address.

I would not suggest memcache for this purpose, but instead a sql database (perhaps a dedicated database instance) or Redis. Memcache is optimize as a temporary data store. You purposefully want a persistent data store, which sql or redis do provide.

0

Approach one,

  1. Increase the session and cookie lifetime as required.
  2. Move session from file-based sessions to Memcached. This can be done in php.ini.

So basically you give the longest session for all users. And then maybe you can write a rule or cronjob for invalidating sessions of the users of the roles you need shorter span.

Approach two, I guess better https://www.drupal.org/project/persistent_login

See: http://www.jaspan.com/improved_persistent_login_cookie_best_practice

1
  • 1
    jaspan.com returns a white screen. Remember to always include a summary when linking blog articles. As they can go 404 any time, what value has this link then?
    – leymannx
    Commented Dec 28, 2018 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.