Skip to content

[HttpFoundation] Add a way to avoid the session be written at each request #9119

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
Sep 30, 2013

Conversation

adrienbrault
Copy link
Contributor

Q A
Bug fix? no
New feature? yes
BC breaks? no (maybe the DI config ?)
Deprecations? no
Tests pass? yes
Fixed tickets N/A
License MIT
Doc PR symfony/symfony-docs#3017

@fabpot
Copy link
Member

fabpot commented Sep 26, 2013

ping @Drak

{
$session = $this->wrappedSessionHandler->read($sessionId);

$this->readSessions[$sessionId] = $session;
Copy link

Choose a reason for hiding this comment

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

What happens on session regenerate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess that write wont be able to know if the session has been modified or not and will save it

@ghost
Copy link

ghost commented Sep 26, 2013

This PR is an interesting concept - without accepting or rejecting here are some thoughts:

The problem is that once a session starts, technically it should always be written after each request because if not, the meta-data would not be updated accurately. That would lead to unpredictable results for code that relies on metadata - like session idle time expiry (which could be really important in secure applications). That is my big objection to the other PRs I've seen that try to limit session writes only if the session attributes/flashes are updated - the session is always updated each session, so it should be written each time.

I'm a big fan of feature configurability, and something like this could be useful in some less security critical applications so long as it's not on by default because it would be unsuitable for some applications, e.g. a session idle period could be longer than expected because of update threshold setting. This would have to be well documented.

It's certainly the best idea I've seen yet. There are other possibilities too, again using a proxy on the session handler to limit writes under certain conditions. In Zikula we do that for guest sessions (where our userid=0).

Remember proxies work in all cases except for native session handlers under PHP 5.3: mostly we use user handlers anyway. Just a point for documentation.

@@ -222,6 +222,19 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
->scalarNode('gc_probability')->end()
->scalarNode('gc_maxlifetime')->end()
->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end()
->scalarNode('metadata_update_threshold')
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't it be an integerNode ?

@adrienbrault
Copy link
Contributor Author

@Drak This should only make the session last less time in some cases, but not longer.

@ghost
Copy link

ghost commented Sep 26, 2013

I must say, that I certainly don't oppose this PR. I've been quite against the other proposals in this area so far, but this seems quite reasonable. It's clean, optional, and it will be well documented. I need more time to review the code and digest it, but in principal it seems ok to me.

@ghost
Copy link

ghost commented Sep 27, 2013

@fabpot - I spent a long while thinking about this PR and I do think it's really good. It would make a nice addition. It's completely BC, nothing breaks as far as I can see.

@fabpot
Copy link
Member

fabpot commented Sep 27, 2013

@adrienbrault Can you work on adding some docs for it?

@adrienbrault
Copy link
Contributor Author

Sure.

Btw, do you have another name idea for the wrap_handler_write_check config name ?

@adrienbrault
Copy link
Contributor Author

Doc PR: symfony/symfony-docs#3017

@fabpot
Copy link
Member

fabpot commented Sep 28, 2013

@adrienbrault docs look good to me except that you forgot to mention @Drak warning ("Remember proxies work in all cases except for native session handlers under PHP 5.3: mostly we use user handlers anyway.")

@Drak just that to double-check your above comment:

  • You says there are other possibilities like using a proxy. AFAIU, this is the approach used here. Can you elaborate on the other possibilities?
  • You say that the session must be written each time because of the metadata. But if you configure the threshold to a value under the session expiration limit, I don't see any drawbacks. Do I miss something here?

@ghost
Copy link

ghost commented Sep 28, 2013

@fabpot Regarding the proxy mechanism and PHP 5.3 maybe I will point this out in the Sessions docs more clearly. I added proxy to mimic the PHP 5.4 feature of the SessionHandler class which always proxies the session handler interface (native or userland) directly in C. Under PHP 5.3 our proxy intercepts any userland save handler and also but only exposes some metadata for native savehandlers since it cant do any more.

I mean there are other uses of the proxy to reduce session writes, for example in Zikula the proxy is useraware and does not persist unauthenticated users. You could also make it user-agent aware and not persist sessions for google-bot et al. This is the best place because code still relies on sessions to be started. Preventing the persist is the best strategy in those cases.

Regarding the meta-data, @adrienbrault answered my questions, so yes, I do not see any drawbacks. This is a really nice use of the proxy mechanism and I don't see any drawbacks. I was just being cautious. I still believe it must be well documented because it does alter expected behaviour, but that's not a criticism, just a good for the developer to know what the codes effects are.

Basically this PR will cause the session to be updated if the content has changed, but not if there only a metadata change AND a certain time period has elapsed. It's brilliant.

@ghost
Copy link

ghost commented Sep 28, 2013

@adrienbrault how about write_frequency_check?

@adrienbrault
Copy link
Contributor Author

The WriteCheckSessionHandler has nothing to do with frequency. Hmm

What about prevent_unmodified_writes ? skip_unmodified_writes

@ghost
Copy link

ghost commented Sep 28, 2013

@adrienbrault That's misleading IMO because what you are doing is changing the granularity at which the metadata is updated and thus changing the session data. It's not just a matter of whether other session data has been modified, it's all about the timing and frequency - so something that reflects that would be better.

@adrienbrault
Copy link
Contributor Author

@Drak but there are 2 different settings that can be used in different
cases, or I may be missing something ?

On Saturday, September 28, 2013, Drak wrote:

@adrienbrault https://github.com/adrienbrault That's misleading IMO
because what you are doing is changing the granularity at which the
metadata is updated and thus changing the session data. It's not just a
matter of whether other session data has been modified, it's all about the
timing and frequency - so something that reflects that would be better.


Reply to this email directly or view it on GitHubhttps://github.com//pull/9119#issuecomment-25294289
.

@ghost
Copy link

ghost commented Sep 28, 2013

@adrienbrault as I understand it, one enables the feature, the other configures the threshold. So the enable toggle should be named write_frequency_check (boolean) and the timing with metadata_update_threshold (integer) - you should be clear in the documentation about the units. or, am I missing something?

@adrienbrault
Copy link
Contributor Author

@Drak metadata_update_threshold will change how often the metadata updated field will be updated, even if wrap_handler_write_check is not configured. On the other hand, wrap_handler_write_check will prevent the session from being written if it has not been modified; even though it should always be modified if metadata_update_threshold is not configured.

I created 2 different settings because the WriteCheckSessionHandler could be useful and used in a context where the Session class is not used (so no metadata). But is that possible with the FrameworkBundle ?

Maybe we should only have 1 setting in the FrameworkBundle configuration ? metadata_update_threshold false would disable the whole thing, and if metadata_update_threshold is an integer it will enable both the WriteCheckSessionHandler and the metadata stuff.

@ghost
Copy link

ghost commented Sep 28, 2013

@adrienbrault sure, but in reality metadata_update_threshold doesn't make sense without the proxy being enabled since it will still be written (which is normal). It has to be used in-conjunction with the proxy. Your cookbook entry is OK for the framework bundle, but you also need example code and how to instantiate for people just using the HttpFoundation component.

@ghost
Copy link

ghost commented Sep 28, 2013

@adrienbrault Sorry I didn't answer the last part. I think it would be better to have one setting, which when false or 0 does nothing, and if you set a value, it sets up the proxy and also sets the threshold in the metadata object.

@adrienbrault
Copy link
Contributor Author

@Drak Thanks, will do that

@adrienbrault
Copy link
Contributor Author

Updated along with the documentation PR

->integerNode('metadata_update_threshold')
->defaultValue('0')
->info(
'time to wait between 2 session metadata updates'.PHP_EOL.
Copy link
Member

Choose a reason for hiding this comment

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

I would prefer just one sentence without a line break.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@fabpot
Copy link
Member

fabpot commented Sep 30, 2013

Apparently, it breaks a test: src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php

@adrienbrault
Copy link
Contributor Author

Use of undefined constant PHP_SESSION_NONE - assumed 'PHP_SESSION_NONE'

Only failing on PHP 5.3

http://php.net/manual/en/function.session-status.php

(PHP >=5.4.0)

I don't think this is related to this PR

@ghost
Copy link

ghost commented Sep 30, 2013

@adrienbrault that's not related to this PR for sure. It comes from DefaultCsrfProvider - so I guess that's a bug in the code there since it shouldnt happen under PHP 5.3 @bschussek

@@ -222,6 +222,10 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
->scalarNode('gc_probability')->end()
->scalarNode('gc_maxlifetime')->end()
->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end()
->integerNode('metadata_update_threshold')
->defaultValue('0')
->info('time to wait between 2 session metadata updates, it will also prevent the session handler to write if the session has not changed')
Copy link

Choose a reason for hiding this comment

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

You should mention what the units are 1 seconds, millisecond etc?

@fabpot fabpot merged commit 38f02ea into symfony:master Sep 30, 2013
@ghost
Copy link

ghost commented Sep 30, 2013

👍

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

Successfully merging this pull request may close these issues.

3 participants