1313
1414use FOS \HttpCache \UserContext \HashGenerator ;
1515use Symfony \Component \EventDispatcher \EventSubscriberInterface ;
16+ use Symfony \Component \HttpFoundation \Request ;
1617use Symfony \Component \HttpFoundation \RequestMatcherInterface ;
1718use Symfony \Component \HttpKernel \Event \FilterResponseEvent ;
1819use Symfony \Component \HttpKernel \Event \GetResponseEvent ;
@@ -61,12 +62,22 @@ class UserContextSubscriber implements EventSubscriberInterface
6162 */
6263 private $ ttl ;
6364
65+ /**
66+ * Used to exclude anonymous requests (no authentication nor session) from user hash sanity check.
67+ * It prevents issues when the hash generator that is used returns a customized value for anonymous users,
68+ * that differs from the documented, hardcoded one.
69+ *
70+ * @var RequestMatcherInterface
71+ */
72+ private $ anonymousRequestMatcher ;
73+
6474 public function __construct (
6575 RequestMatcherInterface $ requestMatcher ,
6676 HashGenerator $ hashGenerator ,
6777 array $ userIdentifierHeaders = array ('Cookie ' , 'Authorization ' ),
6878 $ hashHeader = 'X-User-Context-Hash ' ,
69- $ ttl = 0
79+ $ ttl = 0 ,
80+ RequestMatcherInterface $ anonymousRequestMatcher = null
7081 ) {
7182 if (!count ($ userIdentifierHeaders )) {
7283 throw new \InvalidArgumentException ('The user context must vary on some request headers ' );
@@ -76,6 +87,7 @@ public function __construct(
7687 $ this ->userIdentifierHeaders = $ userIdentifierHeaders ;
7788 $ this ->hashHeader = $ hashHeader ;
7889 $ this ->ttl = $ ttl ;
90+ $ this ->anonymousRequestMatcher = $ anonymousRequestMatcher ;
7991 }
8092
8193 /**
@@ -93,7 +105,7 @@ public function onKernelRequest(GetResponseEvent $event)
93105 }
94106
95107 if (!$ this ->requestMatcher ->matches ($ event ->getRequest ())) {
96- if ($ event ->getRequest ()->headers ->has ($ this ->hashHeader )) {
108+ if ($ event ->getRequest ()->headers ->has ($ this ->hashHeader ) && ! $ this -> isAnonymous ( $ event -> getRequest ()) ) {
97109 $ this ->hash = $ this ->hashGenerator ->generateHash ();
98110 }
99111
@@ -120,6 +132,20 @@ public function onKernelRequest(GetResponseEvent $event)
120132 $ event ->setResponse ($ response );
121133 }
122134
135+ /**
136+ * Tests if $request is an anonymous request or not.
137+ *
138+ * For backward compatibility reasons, true will be returned if no anonymous request matcher was provided.
139+ *
140+ * @param Request $request
141+ *
142+ * @return bool
143+ */
144+ private function isAnonymous (Request $ request )
145+ {
146+ return $ this ->anonymousRequestMatcher ? $ this ->anonymousRequestMatcher ->matches ($ request ) : false ;
147+ }
148+
123149 /**
124150 * Add the context hash header to the headers to vary on if the header was
125151 * present in the request.
0 commit comments