AFAICT there is no API to start a session. The best way appears to be to store something in $_SESSION: see http://drupal.stackexchange.com/questions/163142/what-is-the-right-way-t...
But that means that every module that might want to ensure a session is started needs to store junk data in $_SESSION. This is not ideal (and indeed the patch at #2488116: Document the session subsystem says the amount of data in the session should be kept to a minimum).
There should instead be a forceStart() method on SessionManager.
Issue fork drupal-2865991
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
fgmActually, for the Flag use case in
FlagService::populateFlaggerDefaults()
where this "need" appears, creating the session for all anonymous visitors is a performance hog because, while it makes perfect sense to create sessions for anon users to keep track of their invididual likes; it means that the mere fact of visiting a page with a flag on a node causes the entire site visit after that not to remain anonymous and pierce caches, including proxies, because the session cookie is opaque.The technique we've used on similar needs (keeping track of anonymous info) is to add a non-opaque cookie (with added checksum if security is needed), and only create it when data needs to be stored in it, preserving cacheability for other users.
Comment #3
joachim CreditAttribution: joachim commented> Actually, for the Flag use case in FlagService::populateFlaggerDefaults() where this "need" appears, creating the session for all anonymous visitors is a performance hog because,
I've just had a look at the code, and I see what you mean -- we're starting a session just for looking at a flag link. I agree that's wrong -- could you file a bug report on Flag please?
However, that doesn't change that there is a need for this API. In the Flag case, once an anon user clicks a flag link, we need to make sure there is a session for them, and there should be a better way than setting $_SESSION['some irrelevant key'] = TRUE.
Comment #4
fgmFollowup added as #2894095: Enabling a flag adds session cookies to anonymous users.
Back to this issue: strictly speaking, I wonder what could be the purpose of having a session without having anything in it, considering how sessions cost in performance in the general case. What would it bring to the module starting such a session without content ?
Comment #5
joachim CreditAttribution: joachim commented> I wonder what could be the purpose of having a session without having anything in it, considering how sessions cost in performance in the general case. What would it bring to the module starting such a session without content ?
In the Flag use case, we don't need anything in the session. We just need it to exist and have an ID that persists. The current code just puts junk in to force that:
As you can guess, we're never going to use
$_SESSION['flag'] = TRUE;
. We're not going to need to check for it. We only had to put it there to cause a session to properly start.Comment #6
fgmThanks for the answer, but to me it still remains unclear: what is the value of having this anonymous user session id until there is anything actually stored for that session ? I don't see where in the Flag code base that ID is used until some flagging action is actually performed, at which point is seems normal to start the session.
Comment #7
joachim CreditAttribution: joachim commented> until some flagging action is actually performed, at which point is seems normal to start the session.
Yup, that's it. When a flagging action is performed by an anonymous user, a session should be started.
The point of this issue is that I think there should be a cleaner way of starting the session than doing this:
Comment #8
joachim CreditAttribution: joachim commented> what is the value of having this anonymous user session id until there is anything actually stored for that session
It occurs to me belatedly that perhaps the bit we're misunderstanding each other on is that Flag doesn't need to store any data in the actual session. It only needs a session ID which it saves as a field value on the Flagging entity.
Comment #9
fgmThis is perfectly clear, thanks, not a problem.
Comment #15
znerol CreditAttribution: znerol commentedComment #16
znerol CreditAttribution: znerol commentedDrupal cleans up empty sessions (and associated cookies) for the reasons fgm already stated. Even if there would be an API to forcibly start a session, the only way to keep it open across request would be to store something in it (even if it is a
keep-it-open
flag.The flag module should generate an identifier whenever the first flag was set by an anonymous user and store that in the session as well as in the flag entity. On subsequent requests, this identifier can be used to locate existing flag entities as well as to associate new ones. As soon as the user clears the last flag, the module needs to clear the identifier from the session.
IMHO this is a wontfix.
Comment #17
joachim CreditAttribution: joachim commented> Even if there would be an API to forcibly start a session, the only way to keep it open across request would be to store something in it (even if it is a keep-it-open flag.
Right. So this issue would provide a clear, simple API that takes care of storing one thing in the session to keep it open. At the moment, modules are all having to dump their arbitrary junk into sessions.
Comment #18
andypostAs @joachim said #17 ++
core provides shared temp storage but no common API to bound it to session
looks it needs summary update
Comment #19
andypostOTOH Probably core could suggest to use Symfony session native way to contrib
Comment #20
andypostProbably I could move masquerade session flag to session bad to better control flag operations and logging
Comment #21
znerol CreditAttribution: znerol commentedTo be clear. The thing which intends to enforce a session also is responsible to release that enforcement as soon as it is not necessary anymore. Thus, client code needs its own key/identifier anyway. Please let's just keep to the symfony API (i.e., the
SessionInterface
). If you want to make it pretty for the flags module, then I suggest trying to add a custom AttributeBag which you use to abstract that.Comment #22
joachim CreditAttribution: joachim commented> The thing which intends to enforce a session also is responsible to release that enforcement as soon as it is not necessary anymore.
I don't really understand this point. With the use cases I've seen for this, the thing which wants a session wants the session to remain as long as PHP/the site cares to keep it for. There's no release.
> Please let's just keep to the symfony API (i.e., the SessionInterface).
The Symfony API doesn't start sessions if they're empty.
Comment #23
andypostFYI used to try custom bag approach at today's sprint with #3042321-24: Last access by a user should not change after masquerade as that user (D8)
It's really tricky sometimes to access stored data when session reports is not started
Comment #24
andypostFirst feeling is that
\Drupal\Core\Session\MetadataBag
needs method like[get|set|unset]thirstPartyFlag()
Comment #25
znerol CreditAttribution: znerol commentedKeeping anonymous sessions open for no reason renders caches ineffective (both HTTP proxies as well as the browser). This is definitely not something we want to encourage in core.
The
MetadataBag
is exempted when checking whether a session is empty inSessionManager::isSessionObsolete()
. Thus if a session contains nothing more than metadata, the session is destroyed and the session cookie is unset.Comment #26
znerol CreditAttribution: znerol commented@andypost: Opened #3108967: Introduce a container tag to register session bags.
Comment #29
andypostLooks there's nothing left to fix as sessions will use "bags" and no longer care about start/stop state
Comment #30
joachim CreditAttribution: joachim commented> The Symfony API doesn't start sessions if they're empty.
Is this no longer the case?
Comment #36
volegerSo before closing the issue, references from the codebase need to be removed.
Comment #37
andypost@voleger please rebase MR on 10.1.x
Comment #38
joachim CreditAttribution: joachim commented> The Symfony API doesn't start sessions if they're empty.
I still think this isn't the case.
I just tried
$this->session_manager->start();
and
$this->session_manager->getId();
and
$this->session_manager->save();
and none of them created an entry in the sessions table.
Comment #40
andypostMR removes the TODO and sessions should start automatically
Comment #41
joachim CreditAttribution: joachim commentedI don't understand the MR or #40.
The method startSession() in the MR is protected, so not part of the API. It only gets called when you set some data in the private tempstore, which is exactly the problem described by this issue -- that you have to set some data in order to start a session.
Comment #42
znerol CreditAttribution: znerol commentedThe current MR in #3413153: Remove calls to Request::hasSession() removes
PrivateTempStore::startSession()
entirely.I suggest we close this issue here as a won't fix.
Comment #43
andypostAs commited already #3413153: Remove calls to Request::hasSession()