-
Notifications
You must be signed in to change notification settings - Fork 84
Do not sanity check hash of anonymous requests #289
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
Do not sanity check hash of anonymous requests #289
Conversation
|
Travis looks very broken, but I doubt that my changes did that... how stable is the 1.3 branch ? :-) |
|
The test failures have to do with your introduction of |
|
Okay, thank you @ddeboer. |
| * Tests if $request is an anonymous request or not. | ||
| * | ||
| * For backward compatibility reasons, true will be returned if no anonymous request matcher was provided. | ||
| * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please only use Request here, use statements work for annotations too
|
i agree with the solution. if i think this through correctly, things should work unless you manage to re-use a non-anonymous hash with an anonymous request - but that would be a misconfiguration of your application. #274 was about expired sessions, where the server side session has expired, but the session id is still sent in the request. in that case, we find the hash in the cache and do the request with hash and session id, and thus compare hashes (and see that they mismatch, or if the hash was not in the cache, see the "real" anonymous hash, vs the fake hash ez would create on a request without session cookie). @bastnic maybe you can give us your thoughts as well? (btw, i still feel ezpublish would be better off simply do a hash lookup for anonymous users as well and then cache that - its a low overhead keeping many things simpler. for example, the anonymous cache will be duplicated between completely anonymous users and users that are determined by symfony to be anonymous because the session expired or something.) the tests seem to say that the configuration for the anonymous matcher is wrong. |
e204ef7 to
e4dca8a
Compare
|
Review remarks taken care of. |
| * @return bool | ||
| */ | ||
| private function isAnonymous(Request $request) | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets remove the isset here and just say $this->anonymousRequestMatcher ? $this-... or if you don't like this null !== $this->anonymousRequestMatcher ?
|
Hmm, does anyone know what could cause Tests pass except for this error. |
|
the lowest version test fails. i just re-ran that test for the master branch and it works. can you please try rebasing this branch on master? or check the failures, if they are actually caused by a change in this branch? |
|
oh, just noticed this branch is against the 1.3 version. we now have 1.4 and should target 1.4 instead. or indeed master as its a new feature and there will be no 1.5 but 2 hopefully soonish. |
|
Has 1.3 reached end of life in between ? :) 1.3.x is affected by this issue, as far as I can say. |
|
sorry, had lib and bundle open at the same time. the bundle is still at 1.3. so rebase on 1.3 should be the right thing. |
|
Note that iirc, I've done that yesterday. |
|
@dbu is there anything I should do in particular to run the 1.3 tests ? On both by branch and 1.3, after As far as I can tell, it can't find find |
|
maybe you need to remove the cache files our little test symfony app generates? |
HAH, cache, I knew it ! |
3720c45 to
5157bde
Compare
|
One error left: It seems to be fixed in Sf 2.3.4, but the failing test uses 2.3.0 ( Hints, anybody ? @stof maybe ? |
|
+1 with the solution Shouldn't there be some semantic config in order to be able to configure session prefix? |
|
Poke @dbu. As far as I know, the review remarks have been addressed. Let me know if something is missing. If not, I'll squash the commits so that you can merge this :-) |
| { | ||
| if ($request->server->has('AUTHORIZATION') || | ||
| $request->server->has('HTTP_AUTHORIZATION') || | ||
| $request->server->has('PHP_AUTH_USER') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if people use their custom authentication scheme?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i noticed that we have a configuration user_identifier_headers. maybe we should instead of looking for a session cookie or these headers just inject that list of headers and check for those headers.
the idea with cookies is that as we Vary anyways, the caching proxy has to clean up the cookie to not have random js cookie things in it. so we would not need to really go into the individual cookies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does symfony itself look at HTTP_AUTHORIZATION and PHP_AUTH_USER? if so, we should change the default value of user_identifier_header in the config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the idea with cookies is that as we Vary anyways, the caching proxy has to clean up the cookie to not have random js cookie things in it. so we would not need to really go into the individual cookies.
Meaning that a request is anonymous only if it doesn't have any of the headers from user_identifier_headers. The part that checks for custom sessions names should then be removed completely, right ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that HTTP_AUTHORIZATION and PHP_AUTH_USER are server variables, not cookies. The cookie would, afaik, be Authorization in both cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The part that checks for custom sessions names should then be removed completely, right ?
yes, exactly. because we also Vary on those headers, if you send a cookie header with google analytics data in it, you break the cache anyways. this has to be handled on the caching proxy.
it looks like header based authentication is always put into the AUTHORIZATION header: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/ServerBag.php#L94-L98 so cookie and authorization should be enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dbu so to double check here: in default vcl we strip every other cookie other then session. And from what you say this is done somewhere with the Sf proxy as well, so essentially here if there is any cookie, it is session cookie meaning we don't need to loop true them here. Correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is what i think. i just double-checked and for HttpCache, this is in https://github.com/FriendsOfSymfony/FOSHttpCache/blob/master/src/SymfonyCache/UserContextSubscriber.php#L124-L137
for varnish, this is documented here: http://foshttpcache.readthedocs.io/en/latest/varnish-configuration.html#cleaning-the-cookie-header
caching the user context hash without cleaning the cookie header can not work.
|
sorry that i missed this. had a look again, and i think we are almost there. looking over the code one more time, i noticed that we have a inconsistency with what we use for the Vary header. can you look at that please? i was thinking whether we need any documentation, but its probably too low level. |
Honestly glad you say that :-)
Sure, I'll have a look, thank you. |
@dbu that's about the |
|
yes, that was about the comment on the code we discuss. just wanted to summarize what remains open to do. |
17087b9 to
ef71732
Compare
|
Changed the AnonymousRequestMatcher:
|
| { | ||
| private $userIdentifierHeaders; | ||
|
|
||
| public function __construct($userIdentifierHeaders = ['Cookie', 'Authorization']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as this is in the symfony bundle and always created from the service container, i don't think we need to default this. the Configuration.php already defines defaults for user_identifier_headers.
and please typehint array for $userIdentifierHeaders and add a docblock that says that its a list of the header names of headers that make a request not be anonymous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack. Note that UserContextSubscribed does set a default ctor value for them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the default altogether, and updated the unit test.
Rebased on top of 1.3, and cleaned the commits up.
|
apart from #289 (comment) this looks ready to merge. some build fail because composer has too many options and runs out of memory. not related to this PR |
|
Changed. Let me know if it's okay, and I'll cleanup the commits a bit. |
| /** | ||
| * @param array $userIdentifierHeaders List of request headers that authenticate a non-anonymous request | ||
| */ | ||
| public function __construct(array $userIdentifierHeaders = []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my idea was to not specify a default at all, so that calling code is forced to pass an argument and not null. as it is now its is rather dangerous, if anything would go wrong we would simply consider everything anonymous.
|
apart from that 1 comment i am happy with this. please squash the commits as you see fit, and rebase on 1.3 to get the fixed testing setup i just merged. |
Fixes the "Unexpected character in input" notice that happens on Travis, when running tests using the phar version.
2c97a57 to
6492160
Compare
| if (strtolower($header) === 'cookie' && $request->cookies->count()) { | ||
| return false; | ||
| } | ||
| if ($request->headers->has($header)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, one more question: what does symfony request do with the cookie header? is that removed from the header bag? what happens if we have a request with only an empty cookie header? won't we then get in here and see the cookie header, making the previous if on the cookies count kind of pointless? should we do
if ($request->headers->has($header)) {
if (strtolower($header) === 'cookie' && 0 === $request->cookies->count()) {
// ignore empty cookie header
continue;
}
return false;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, with test, @dbu.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the first if with cookie header and nonzero number of cookies is now redundant and should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the if, adjusted the existing test, and added a new case.
|
By the way, once this is merged, do you think we'll be able to tag a new release shortly, @dbu ? |
|
yay, thanks bertrand |
|
ported to master as well, and tagged 1.3.8 |
|
I have a problem with this. I use eZ Platform and a anonymous with cookies (e. g. from piwik) but without the session cookie doesn't use the http cache. Why would only look after cookie count and not after the specific session cookie? |
|
I created a PR for my issue: #421 |
The hardcoded anonymous hash might differ from the one used in the sanity check introduced by this PR. This causes cache expirations for us since anonymous requests don't match.
This change excludes anonymous requests, using an
AnonymousRequestMatcher, from this sanity check.ezsystems/ezpublish-kernel#1601 describes the consequences and way to reproduce on ezplatform.
TODO