8000 [Kernel] ensure session is saved before sending response by Tobion · Pull Request #12341 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Kernel] ensure session is saved before sending response #12341

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

Merged
merged 1 commit into from
Nov 2, 2014

Conversation

Tobion
Copy link
Contributor
@Tobion Tobion commented Oct 28, 2014
Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #6417, #7885
License MIT
Doc PR n/a

Saves the session, in case it is still open, before sending the response.

This ensures several things in case the developer did not save the session explicitly:

  • If a session save handler without locking is used, it ensures the data is available
    on the next request, e.g. after a redirect. PHPs auto-save at script end via
    session_register_shutdown is executed after fastcgi_finish_request. So in this case
    the data could be missing the next request because it might not be saved the moment
    the new request is processed.
  • A locking save handler (e.g. the native 'files') circumvents concurrency problems like
    the one above. By saving the session before long-running things in the terminate event,
    we ensure the session is not blocked longer than needed.
  • When regenerating the session ID no locking is involved in PHPs session design. See
    https://bugs.php.net/bug.php?id=61470 for a discussion. So in this case, the session must
    be saved anyway before sending the headers with the new session ID. Otherwise session
    data could get lost again for concurrent requests with the new ID. One result could be
    that you get logged out after just logging in.

This listener should be executed as one of the last listeners, so that previous listeners
can still operate on the open session. This prevents the overhead of restarting it.
Listeners after closing the session can still work with the session as usual because
Symfonys session implementation starts the session on demand. So writing to it after
it is saved will just restart it.

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is not such class in version 2.3, it was introduced in version 2.4.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stloyd thanks. I fixed it.

@Tobion Tobion force-pushed the save-session-listener branch from bb0ffc4 to 0e677eb Compare October 28, 2014 15:41
@fabpot
Copy link
Member
fabpot commented Oct 28, 2014

@Tobion So, I think you need to also submit a PR for 2.5.

@stof
Copy link
Member
stof commented Oct 28, 2014

instead of doing it on master kernel.response with a low priority, which can still break for people streaming responses for instance, I think it would be better to do it on kernel.terminate with a high priority (the goal being to save the session before doing the heavy termination logic)

@Tobion
Copy link
Contributor Author
Tobion commented Oct 28, 2014

@stof that's useless. Again the point, as documented, is to save the session before it is send(). Terminate would be too late.

@stof
Copy link
Member
stof commented Oct 28, 2014

@Tobion the issue is that this will also save before the processing of streamed responses. The right time to save is actually when finishing the send() call (but before the termination logic), not before the send() call

@Tobion
Copy link
Contributor Author
Tobion commented Oct 28, 2014

@stof what exactly is the problem with streamed responses?
And it must be done BEFORE fast_cgi_finish_request which is inside the send() call. Not after finishing it.

@Tobion
Copy link
Contributor Author
Tobion commented Oct 28, 2014

@fabpot After this is merged into 2.3 and 2.4, I can make a PR on 2.4 to change the listener to listen on finish_request instead. But actually it's optional and not required.

@nicolas-grekas
Copy link
Member

Don't you fear getting bug reports from users changing session state after the event?
Is there a way to trigger some warning/exception when the session is modified but already closed?

@linaori
Copy link
Contributor
linaori commented Oct 28, 2014

This might actually solve some issues I have with a database session storage and a Captcha throwing 404s because it has no code in the session (yet).

@Tobion
Copy link
Contributor Author
Tobion commented Oct 28, 2014

@nicolas-grekas no because symfony session starts on demand. So writing to the session after it closed, still works as expected.

@Tobion
Copy link
Contributor Author
Tobion commented Oct 29, 2014

@stof streamed responses are sent via https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/EventListener/StreamedResponseListener.php aren't they? And we want the session to be saved before the headers are sent. So the SaveSessionListener should have a higher priority that the StreamedResponseListener.

@fabpot
Copy link
Member
fabpot commented Oct 30, 2014

👍

@fabpot
Copy link
Member
fabpot commented Nov 2, 2014

Thank you @Tobion.

@fabpot fabpot merged commit b7bfef0 into symfony:2.3 Nov 2, 2014
fabpot added a commit that referenced this pull request Nov 2, 2014
…Tobion)

This PR was merged into the 2.3 branch.

Discussion
----------

[Kernel] ensure session is saved before sending response

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #6417, #7885
| License       | MIT
| Doc PR        | n/a

Saves the session, in case it is still open, before sending the response.

This ensures several things in case the developer did not save the session explicitly:

- If a session save handler without locking is used, it ensures the data is available
on the next request, e.g. after a redirect. PHPs auto-save at script end via
session_register_shutdown is executed after fastcgi_finish_request. So in this case
the data could be missing the next request because it might not be saved the moment
the new request is processed.

- A locking save handler (e.g. the native 'files') circumvents concurrency problems like
the one above. By saving the session before long-running things in the terminate event,
we ensure the session is not blocked longer than needed.

- When regenerating the session ID no locking is involved in PHPs session design. See
https://bugs.php.net/bug.php?id=61470 for a discussion. So in this case, the session must
be saved anyway before sending the headers with the new session ID. Otherwise session
data could get lost again for concurrent requests with the new ID. One result could be
that you get logged out after just logging in.

This listener should be executed as one of the last listeners, so that previous listeners
can still operate on the open session. This prevents the overhead of restarting it.
Listeners after closing the session can still work with the session as usual because
 Symfonys session implementation starts the session on demand. So writing to it after
it is saved will just restart it.

Commits
-------

b7bfef0 [Kernel] ensure session is saved before sending response
fabpot added a commit that referenced this pull request Nov 2, 2014
This PR was merged into the 2.3 branch.

Discussion
----------

[Session] remove invalid hack in session regenerate

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

The original issue #7380 was just caused because the developer missed to save the session before doing the redirect. That's all. Such mistakes won't happen anymore with #12341

This reverts #8270 and following. Also it makes absolutely no sense to do this only for the `files` save handler which creates huge inconsistencies. All save handlers are affected and it's more a documentation thing.

Commits
-------

703d906 [Session] remove invalid workaround in session regenerate
@Tobion Tobion deleted the save-session-listener branch November 2, 2014 00:47
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

Successfully merging this pull request may close these issues.

6 participants
0