diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 2f6ece9b92809..6903fb4ed455d 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,20 @@ in 2.7 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1 +* 2.7.47 (2018-05-21) + + * bug #26781 [Form] Fix precision of MoneyToLocalizedStringTransformer's divisions on transform() (syastrebov) + * bug #27286 [Translation] Add Occitan plural rule (kylekatarnls) + * bug #27246 Disallow invalid characters in session.name (ostrolucky) + * bug #24805 [Security] Fix logout (MatTheCat) + * bug #27141 [Process] Suppress warnings when open_basedir is non-empty (cbj4074) + * bug #27250 [Session] limiting :key for GET_LOCK to 64 chars (oleg-andreyev) + * bug #27237 [Debug] Fix populating error_get_last() for handled silent errors (nicolas-grekas) + * bug #27236 [Filesystem] Fix usages of error_get_last() (nicolas-grekas) + * bug #27152 [HttpFoundation] use brace-style regex delimiters (xabbuh) + * feature #24896 Add CODE_OF_CONDUCT.md (egircys) + * bug #27067 [HttpFoundation] Fix setting session-related ini settings (e-moe) + * 2.7.46 (2018-04-27) * bug #26831 [Bridge/Doctrine] count(): Parameter must be an array or an object that implements Countable (gpenverne) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index 9f76090b789b7..522a83664793c 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,15 @@ in 2.8 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.8.0...v2.8.1 +* 2.8.41 (2018-05-25) + + * bug #27359 [HttpFoundation] Fix perf issue during MimeTypeGuesser intialization (nicolas-grekas) + * security #cve-2018-11408 [SecurityBundle] Fail if security.http_utils cannot be configured + * security #cve-2018-11406 clear CSRF tokens when the user is logged out + * security #cve-2018-11385 Adding session authentication strategy to Guard to avoid session fixation + * security #cve-2018-11385 Adding session strategy to ALL listeners to avoid *any* possible fixation + * security #cve-2018-11386 [HttpFoundation] Break infinite loop in PdoSessionHandler when MySQL is in loose mode + * 2.8.40 (2018-05-21) * bug #26781 [Form] Fix precision of MoneyToLocalizedStringTransformer's divisions on transform() (syastrebov) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index bc4ebf6f78139..672246e7f9da8 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -17,9 +17,9 @@ Symfony is the result of the work of many people who made the code better - Johannes S (johannes) - Jakub Zalas (jakubzalas) - Kris Wallsmith (kriswallsmith) + - Maxime Steinhausser (ogizanagi) - Ryan Weaver (weaverryan) - Javier Eguiluz (javier.eguiluz) - - Maxime Steinhausser (ogizanagi) - Grégoire Pineau (lyrixx) - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) @@ -35,17 +35,17 @@ Symfony is the result of the work of many people who made the code better - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) + - Samuel ROZE (sroze) - Jules Pietri (heah) - Eriksen Costa (eriksencosta) - Guilhem Niot (energetick) - Sarah Khalil (saro0h) - - Samuel ROZE (sroze) + - Yonel Ceruto (yonelceruto) - Jonathan Wage (jwage) - Hamza Amrouche (simperfit) - Diego Saint Esteben (dosten) - - Yonel Ceruto (yonelceruto) - - Alexandre Salomé (alexandresalome) - Iltar van der Berg (kjarli) + - Alexandre Salomé (alexandresalome) - William Durand (couac) - ornicar - Francis Besset (francisbesset) @@ -59,9 +59,9 @@ Symfony is the result of the work of many people who made the code better - Henrik Bjørnskov (henrikbjorn) - Dany Maillard (maidmaid) - Miha Vrhovnik + - Kevin Bond (kbond) - Tobias Nyholm (tobias) - Diego Saint Esteben (dii3g0) - - Kevin Bond (kbond) - Konstantin Kudryashov (everzet) - Alexander M. Turek (derrabus) - Bilal Amarni (bamarni) @@ -83,12 +83,12 @@ Symfony is the result of the work of many people who made the code better - Dariusz Górecki (canni) - Issei Murasawa (issei_m) - Douglas Greenshields (shieldo) + - David Maicher (dmaicher) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) - Graham Campbell (graham) - Daniel Holmes (dholmes) - - David Maicher (dmaicher) - Dariusz Ruminski - Toni Uebernickel (havvg) - Bart van den Burg (burgov) @@ -103,9 +103,9 @@ Symfony is the result of the work of many people who made the code better - Maxime STEINHAUSSER - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) + - Grégoire Paris (greg0ire) - Brice BERNARD (brikou) - Baptiste Clavié (talus) - - Grégoire Paris (greg0ire) - marc.weistroff - lenar - Alexander Schwenn (xelaris) @@ -139,21 +139,21 @@ Symfony is the result of the work of many people who made the code better - Sebastian Hörl (blogsh) - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) + - Jérôme Vasseur (jvasseur) + - Valentin Udaltsov (vudaltsov) + - gadelat (gadelat) - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) - - Jérôme Vasseur (jvasseur) - Jérémie Augustin (jaugustin) - Andréia Bohner (andreia) - Philipp Wahala (hifi) - Julien Falque (julienfalque) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) - - gadelat (gadelat) - jwdeitch - Teoh Han Hui (teohhanhui) - Mikael Pajunen - Joel Wurtz (brouznouf) - - Valentin Udaltsov (vudaltsov) - Chris Wilkinson (thewilkybarkid) - Oleg Voronkovich - Vyacheslav Pavlov @@ -226,6 +226,7 @@ Symfony is the result of the work of many people who made the code better - Julien Brochet (mewt) - Leo Feyer - Tristan Darricau (nicofuma) + - Nikolay Labinskiy (e-moe) - Michaël Perrin (michael.perrin) - Marcel Beerta (mazen) - Loïc Faugeron @@ -260,6 +261,7 @@ Symfony is the result of the work of many people who made the code better - Kristen Gilden (kgilden) - Pierre-Yves LEBECQ (pylebecq) - Jordan Samouh (jordansamouh) + - Baptiste Lafontaine (magnetik) - Jakub Kucharovic (jkucharovic) - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) @@ -270,7 +272,6 @@ Symfony is the result of the work of many people who made the code better - Jan Sorgalla (jsor) - Ray - Tyson Andre - - Nikolay Labinskiy (e-moe) - Chekote - Thomas Adam - Albert Casademont (acasademont) @@ -286,6 +287,7 @@ Symfony is the result of the work of many people who made the code better - Oskar Stark (oskarstark) - Thomas Lallement (raziel057) - Giorgio Premi + - Christian Schmidt - Beau Simensen (simensen) - Michael Hirschler (mvhirsch) - Robert Kiss (kepten) @@ -317,7 +319,6 @@ Symfony is the result of the work of many people who made the code better - Jerzy Zawadzki (jzawadzki) - Wouter J - Ismael Ambrosi (iambrosi) - - Baptiste Lafontaine - François Pluchino (francoispluchino) - Aurelijus Valeiša (aurelijus) - Jan Decavele (jandc) @@ -361,6 +362,7 @@ Symfony is the result of the work of many people who made the code better - Yaroslav Kiliba - Terje Bråten - Mathieu Lechat + - MatTheCat - Robbert Klarenbeek (robbertkl) - JhonnyL - David Badura (davidbadura) @@ -424,7 +426,6 @@ Symfony is the result of the work of many people who made the code better - Jeanmonod David (jeanmonod) - Christopher Davis (chrisguitarguy) - Jan Schumann - - Christian Schmidt - Niklas Fiekas - Markus Bachmann (baachi) - lancergr @@ -437,6 +438,7 @@ Symfony is the result of the work of many people who made the code better - Josip Kruslin - Asmir Mustafic (goetas) - vagrant + - Aurimas Niekis (gcds) - EdgarPE - Florian Pfitzer (marmelatze) - Asier Illarramendi (doup) @@ -514,6 +516,7 @@ Symfony is the result of the work of many people who made the code better - De Cock Xavier (xdecock) - Almog Baku (almogbaku) - Scott Arciszewski + - Xavier HAUSHERR - Norbert Orzechowicz (norzechowicz) - Denis Charrier (brucewouaigne) - Matthijs van den Bos (matthijs) @@ -529,7 +532,6 @@ Symfony is the result of the work of many people who made the code better - Dawid Pakuła (zulusx) - Florian Rey (nervo) - Rodrigo Borrego Bernabé (rodrigobb) - - MatTheCat - Denis Gorbachev (starfall) - Peter van Dommelen - Tim van Densen @@ -563,6 +565,7 @@ Symfony is the result of the work of many people who made the code better - Mantas Var (mvar) - Sebastian Krebs - Jean-Christophe Cuvelier [Artack] + - Simon DELICATA - alcaeus - Fred Cox - vitaliytv @@ -580,6 +583,7 @@ Symfony is the result of the work of many people who made the code better - James Johnston - Sinan Eldem - Alexandre Dupuy (satchette) + - Malte Blättermann - Andre Rømcke (andrerom) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) @@ -604,7 +608,6 @@ Symfony is the result of the work of many people who made the code better - Michal Trojanowski - David Fuhr - Kamil Kokot (pamil) - - Aurimas Niekis (gcds) - Max Grigorian (maxakawizard) - mcfedr (mcfedr) - Rostyslav Kinash @@ -721,6 +724,7 @@ Symfony is the result of the work of many people who made the code better - Adam Szaraniec (mimol) - Yosmany Garcia (yosmanyga) - Wouter de Wild + - Antoine M (amakdessi) - Degory Valentine - izzyp - Benoit Lévêque (benoit_leveque) @@ -730,6 +734,7 @@ Symfony is the result of the work of many people who made the code better - Xavier Lacot (xavier) - possum - Denis Zunke (donalberto) + - Philipp Cordes - Ahmed TAILOULOUTE (ahmedtai) - Olivier Maisonneuve (olineuve) - Masterklavi @@ -749,7 +754,6 @@ Symfony is the result of the work of many people who made the code better - Adrien Lucas (adrienlucas) - Zhuravlev Alexander (scif) - James Michael DuPont - - Xavier HAUSHERR - Tom Klingenberg - Christopher Hall (mythmakr) - Patrick Dawkins (pjcdawkins) @@ -802,6 +806,7 @@ Symfony is the result of the work of many people who made the code better - corphi - grizlik - Derek ROTH + - Ben Johnson - Dmytro Boiko (eagle) - Shin Ohno (ganchiku) - Geert De Deckere (geertdd) @@ -882,6 +887,7 @@ Symfony is the result of the work of many people who made the code better - Michael Tibben - Billie Thompson - Sander Marechal + - Icode4Food (icode4food) - Radosław Benkel - jean pasqualini (darkilliant) - Ross Motley (rossmotley) @@ -993,6 +999,7 @@ Symfony is the result of the work of many people who made the code better - DerManoMann - Olaf Klischat - orlovv + - Jonathan Hedstrom - Peter Smeets (darkspartan) - Jhonny Lidfors (jhonny) - Julien Bianchi (jubianchi) @@ -1005,7 +1012,6 @@ Symfony is the result of the work of many people who made the code better - Andrew Tch - Alexander Cheprasov - Rodrigo Díez Villamuera (rodrigodiez) - - Malte Blättermann - e-ivanov - Jochen Bayer (jocl) - Alex Bowers @@ -1092,9 +1098,11 @@ Symfony is the result of the work of many people who made the code better - Tobias Stöckler - Mario Young - Ilia (aliance) + - Chris McCafferty (cilefen) - Grégoire Penverne (gpenverne) - Mo Di (modi) - Pablo Schläpfer + - Gert de Pagter - Jelte Steijaert (jelte) - Quique Porta (quiqueporta) - stoccc @@ -1177,9 +1185,9 @@ Symfony is the result of the work of many people who made the code better - Andreas Frömer - Philip Frank - Lance McNearney - - Antoine M (amakdessi) - Gonzalo Vilaseca (gonzalovilaseca) - Giorgio Premi + - ncou - Ian Carroll - caponica - Matt Daum (daum) @@ -1197,7 +1205,6 @@ Symfony is the result of the work of many people who made the code better - Tadcka - Beth Binkovitz - Gonzalo Míguez - - Philipp Cordes - Pierre Rineau - Romain Geissler - Adrien Moiruad @@ -1352,6 +1359,7 @@ Symfony is the result of the work of many people who made the code better - Pablo Maria Martelletti (pmartelletti) - Yassine Guedidi (yguedidi) - Waqas Ahmed + - Bert Hekman - Luis Muñoz - Matthew Donadio - Houziaux mike @@ -1450,6 +1458,7 @@ Symfony is the result of the work of many people who made the code better - Yannick Warnier (ywarnier) - Kevin Decherf - Jason Woods + - Oleg Andreyev - klemens - dened - Dmitry Korotovsky @@ -1508,6 +1517,7 @@ Symfony is the result of the work of many people who made the code better - Pierre Rineau - Maxim Lovchikov - adenkejawen + - Florent SEVESTRE (aniki-taicho) - Ari Pringle (apringle) - Dan Ordille (dordille) - Jan Eichhorn (exeu) @@ -1759,7 +1769,6 @@ Symfony is the result of the work of many people who made the code better - Matt Janssen - Ben Miller - Peter Gribanov - - Ben Johnson - kwiateusz - David Soria Parra - Sergiy Sokolenko @@ -1889,6 +1898,7 @@ Symfony is the result of the work of many people who made the code better - Julien Sanchez (sumbobyboys) - Guillermo Gisinger (t3chn0r) - Markus Tacker (tacker) + - Tarmo Leppänen (tarlepp) - Tyler Stroud (tystr) - Moritz Kraft (userfriendly) - Víctor Mateo (victormateo) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 3e7b75ba127e2..06bd65eae4746 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -20,7 +20,7 @@ "ext-xml": "*", "symfony/asset": "~2.7|~3.0.0", "symfony/class-loader": "~2.1|~3.0.0", - "symfony/dependency-injection": "~2.8", + "symfony/dependency-injection": "~2.8.41", "symfony/config": "~2.8", "symfony/event-dispatcher": "~2.8|~3.0.0", "symfony/finder": "^2.0.5|~3.0.0", diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php index 3dd18944de9f3..ba523382b66ba 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSessionDomainConstraintPass.php @@ -26,7 +26,7 @@ class AddSessionDomainConstraintPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { - if (!$container->hasParameter('session.storage.options') || !$container->has('security.http_utils')) { + if (!$container->hasParameter('session.storage.options')) { return; } @@ -34,6 +34,7 @@ public function process(ContainerBuilder $container) $domainRegexp = empty($sessionOptions['cookie_domain']) ? '%s' : sprintf('(?:%%s|(?:.+\.)?%s)', preg_quote(trim($sessionOptions['cookie_domain'], '.'))); $domainRegexp = (empty($sessionOptions['cookie_secure']) ? 'https?://' : 'https://').$domainRegexp; + // if the service doesn't exist, an exception must be thrown - ignoring would put security at risk $container->findDefinition('security.http_utils')->addArgument(sprintf('{^%s$}i', $domainRegexp)); } } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfTokenClearingLogoutHandlerPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfTokenClearingLogoutHandlerPass.php new file mode 100644 index 0000000000000..d4d28ecc4eb35 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfTokenClearingLogoutHandlerPass.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Christian Flothmann + */ +class RegisterCsrfTokenClearingLogoutHandlerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (!$container->has('security.logout_listener') || !$container->has('security.csrf.token_storage')) { + return; + } + + $csrfTokenStorage = $container->findDefinition('security.csrf.token_storage'); + $csrfTokenStorageClass = $container->getParameterBag()->resolveValue($csrfTokenStorage->getClass()); + + if (!is_subclass_of($csrfTokenStorageClass, 'Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface')) { + return; + } + + $container->register('security.logout.handler.csrf_token_clearing', 'Symfony\Component\Security\Http\Logout\CsrfTokenClearingLogoutHandler') + ->addArgument(new Reference('security.csrf.token_storage')) + ->setPublic(false); + + $container->findDefinition('security.logout_listener')->addMethodCall('addHandler', array(new Reference('security.logout.handler.csrf_token_clearing'))); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php index 61649f331a97a..18f5db433e750 100644 --- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle; +use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterCsrfTokenClearingLogoutHandlerPass; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -57,6 +58,7 @@ public function build(ContainerBuilder $container) $extension->addUserProviderFactory(new InMemoryFactory()); $extension->addUserProviderFactory(new LdapFactory()); $container->addCompilerPass(new AddSecurityVotersPass()); - $container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_BEFORE_REMOVING); + $container->addCompilerPass(new RegisterCsrfTokenClearingLogoutHandlerPass()); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php index 7d49ad3dd4ec6..e12f3a64f31fe 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSessionDomainConstraintPassTest.php @@ -96,6 +96,19 @@ public function testNoSession() $this->assertTrue($utils->createRedirectResponse($request, 'http://pirate.com/foo')->isRedirect('http://pirate.com/foo')); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + * @expectedExceptionMessage You have requested a non-existent service "security.http_utils". + */ + public function testNoHttpUtils() + { + $container = new ContainerBuilder(); + $container->setParameter('session.storage.options', array()); + + $pass = new AddSessionDomainConstraintPass(); + $pass->process($container); + } + private function createContainer($sessionStorageOptions) { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php index 7eeb7c21171ce..d3c3b77fd5d61 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php @@ -31,4 +31,22 @@ public function testSessionLessRememberMeLogout() $this->assertNull($cookieJar->get('REMEMBERME')); } + + public function testCsrfTokensAreClearedOnLogout() + { + $client = $this->createClient(array('test_case' => 'LogoutWithoutSessionInvalidation', 'root_config' => 'config.yml')); + $client->getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); + + $client->request('POST', '/login', array( + '_username' => 'johannes', + '_password' => 'test', + )); + + $this->assertTrue($client->getContainer()->get('security.csrf.token_storage')->hasToken('foo')); + $this->assertSame('bar', $client->getContainer()->get('security.csrf.token_storage')->getToken('foo')); + + $client->request('GET', '/logout'); + + $this->assertFalse($client->getContainer()->get('security.csrf.token_storage')->hasToken('foo')); + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/bundles.php new file mode 100644 index 0000000000000..d90f774abde2b --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/bundles.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; + +return array( + new FrameworkBundle(), + new SecurityBundle(), +); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/config.yml new file mode 100644 index 0000000000000..9e5563fea5197 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/config.yml @@ -0,0 +1,26 @@ +imports: + - { resource: ./../config/framework.yml } + +security: + encoders: + Symfony\Component\Security\Core\User\User: plaintext + + providers: + in_memory: + memory: + users: + johannes: { password: test, roles: [ROLE_USER] } + + firewalls: + default: + form_login: + check_path: login + remember_me: true + require_previous_session: false + remember_me: + always_remember_me: true + secret: secret + logout: + invalidate_session: false + anonymous: ~ + stateless: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/routing.yml new file mode 100644 index 0000000000000..1dddfca2f8154 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/routing.yml @@ -0,0 +1,5 @@ +login: + path: /login + +logout: + path: /logout diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index c75bf6ecb9f46..f588b04888161 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.9", "ext-xml": "*", - "symfony/security": "^2.8.40|~3.4.10", + "symfony/security": "^2.8.41|^3.4.11", "symfony/security-acl": "~2.7|~3.0.0", "symfony/http-kernel": "~2.7|~3.0.0", "symfony/polyfill-php70": "~1.0" @@ -27,6 +27,7 @@ "symfony/browser-kit": "~2.7|~3.0.0", "symfony/console": "~2.7|~3.0.0", "symfony/css-selector": "^2.7|~3.0.0", + "symfony/dependency-injection": "~2.8.41", "symfony/dom-crawler": "^2.7|~3.0.0", "symfony/form": "^2.8.18", "symfony/framework-bundle": "^2.8.18", diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php index e3ef45ef672cf..d78c76068234f 100644 --- a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php +++ b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php @@ -80,13 +80,8 @@ public static function reset() */ private function __construct() { - if (FileBinaryMimeTypeGuesser::isSupported()) { - $this->register(new FileBinaryMimeTypeGuesser()); - } - - if (FileinfoMimeTypeGuesser::isSupported()) { - $this->register(new FileinfoMimeTypeGuesser()); - } + $this->register(new FileBinaryMimeTypeGuesser()); + $this->register(new FileinfoMimeTypeGuesser()); } /** @@ -125,18 +120,14 @@ public function guess($path) throw new AccessDeniedException($path); } - if (!$this->guessers) { - $msg = 'Unable to guess the mime type as no guessers are available'; - if (!FileinfoMimeTypeGuesser::isSupported()) { - $msg .= ' (Did you enable the php_fileinfo extension?)'; - } - throw new \LogicException($msg); - } - foreach ($this->guessers as $guesser) { if (null !== $mimeType = $guesser->guess($path)) { return $mimeType; } } + + if (2 === \count($this->guessers) && !FileBinaryMimeTypeGuesser::isSupported() && !FileinfoMimeTypeGuesser::isSupported()) { + throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)'); + } } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 0825ee6ea9899..bb000f5c9a7a0 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -494,6 +494,7 @@ private function doRead($sessionId) $selectSql = $this->getSelectSql(); $selectStmt = $this->pdo->prepare($selectSql); $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $insertStmt = null; do { $selectStmt->execute(); @@ -509,6 +510,11 @@ private function doRead($sessionId) return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; } + if (null !== $insertStmt) { + $this->rollback(); + throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); + } + if (self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block // until other connections to the session are committed. diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 1eee70532ab18..d7ac3985b4457 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,11 +59,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.40'; - const VERSION_ID = 20840; + const VERSION = '2.8.41'; + const VERSION_ID = 20841; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 40; + const RELEASE_VERSION = 41; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; diff --git a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php index d7931c09b2099..89086e5c565c3 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php @@ -116,4 +116,32 @@ public function testRemoveExistingToken() $this->assertSame('TOKEN', $this->storage->removeToken('token_id')); $this->assertFalse($this->storage->hasToken('token_id')); } + + public function testClearRemovesAllTokensFromTheConfiguredNamespace() + { + $this->storage->setToken('foo', 'bar'); + $this->storage->clear(); + + $this->assertFalse($this->storage->hasToken('foo')); + $this->assertArrayNotHasKey(self::SESSION_NAMESPACE, $_SESSION); + } + + public function testClearDoesNotRemoveSessionValuesFromOtherNamespaces() + { + $_SESSION['foo']['bar'] = 'baz'; + $this->storage->clear(); + + $this->assertArrayHasKey('foo', $_SESSION); + $this->assertArrayHasKey('bar', $_SESSION['foo']); + $this->assertSame('baz', $_SESSION['foo']['bar']); + } + + public function testClearDoesNotRemoveNonNamespacedSessionValues() + { + $_SESSION['foo'] = 'baz'; + $this->storage->clear(); + + $this->assertArrayHasKey('foo', $_SESSION); + $this->assertSame('baz', $_SESSION['foo']); + } } diff --git a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php index 306e19ad91bb9..7539852f13f3f 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php @@ -129,4 +129,31 @@ public function testRemoveExistingTokenFromActiveSession() $this->assertSame('TOKEN', $this->storage->removeToken('token_id')); } + + public function testClearRemovesAllTokensFromTheConfiguredNamespace() + { + $this->storage->setToken('foo', 'bar'); + $this->storage->clear(); + + $this->assertFalse($this->storage->hasToken('foo')); + $this->assertFalse($this->session->has(self::SESSION_NAMESPACE.'/foo')); + } + + public function testClearDoesNotRemoveSessionValuesFromOtherNamespaces() + { + $this->session->set('foo/bar', 'baz'); + $this->storage->clear(); + + $this->assertTrue($this->session->has('foo/bar')); + $this->assertSame('baz', $this->session->get('foo/bar')); + } + + public function testClearDoesNotRemoveNonNamespacedSessionValues() + { + $this->session->set('foo', 'baz'); + $this->storage->clear(); + + $this->assertTrue($this->session->has('foo')); + $this->assertSame('baz', $this->session->get('foo')); + } } diff --git a/src/Symfony/Component/Security/Csrf/TokenStorage/ClearableTokenStorageInterface.php b/src/Symfony/Component/Security/Csrf/TokenStorage/ClearableTokenStorageInterface.php new file mode 100644 index 0000000000000..0d6f16b68d0b6 --- /dev/null +++ b/src/Symfony/Component/Security/Csrf/TokenStorage/ClearableTokenStorageInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Csrf\TokenStorage; + +/** + * @author Christian Flothmann + */ +interface ClearableTokenStorageInterface extends TokenStorageInterface +{ + /** + * Removes all CSRF tokens. + */ + public function clear(); +} diff --git a/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php b/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php index e817fdb902af8..e57e98d542433 100644 --- a/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php +++ b/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php @@ -18,7 +18,7 @@ * * @author Bernhard Schussek */ -class NativeSessionTokenStorage implements TokenStorageInterface +class NativeSessionTokenStorage implements ClearableTokenStorageInterface { /** * The namespace used to store values in the session. @@ -96,6 +96,14 @@ public function removeToken($tokenId) return $token; } + /** + * {@inheritdoc} + */ + public function clear() + { + unset($_SESSION[$this->namespace]); + } + private function startSession() { if (\PHP_VERSION_ID >= 50400) { diff --git a/src/Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php b/src/Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php index 7b00e3231b45a..d22b83e8d51de 100644 --- a/src/Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php +++ b/src/Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php @@ -19,7 +19,7 @@ * * @author Bernhard Schussek */ -class SessionTokenStorage implements TokenStorageInterface +class SessionTokenStorage implements ClearableTokenStorageInterface { /** * The namespace used to store values in the session. @@ -92,4 +92,16 @@ public function removeToken($tokenId) return $this->session->remove($this->namespace.'/'.$tokenId); } + + /** + * {@inheritdoc} + */ + public function clear() + { + foreach (array_keys($this->session->all()) as $key) { + if (0 === strpos($key, $this->namespace.'/')) { + $this->session->remove($key); + } + } + } } diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php index 3b62c41253a22..5e6eba339bf64 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -46,6 +46,7 @@ public function __construct(TokenStorageInterface $tokenStorage, EventDispatcher */ public function authenticateWithToken(TokenInterface $token, Request $request) { + $this->migrateSession($request); $this->tokenStorage->setToken($token); if (null !== $this->dispatcher) { @@ -127,4 +128,16 @@ public function handleAuthenticationFailure(AuthenticationException $authenticat is_object($response) ? get_class($response) : gettype($response) )); } + + private function migrateSession(Request $request) + { + if (!$request->hasSession() || !$request->hasPreviousSession()) { + return; + } + + // Destroying the old session is broken in php 5.4.0 - 5.4.10 + // See https://bugs.php.net/63379 + $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; + $request->getSession()->migrate($destroy); + } } diff --git a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php index 0065fe8237c3e..2054c4aa0774e 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php @@ -82,6 +82,9 @@ final public function handle(GetResponseEvent $event) if (null !== $this->logger) { $this->logger->info('Pre-authentication successful.', array('token' => (string) $token)); } + + $this->migrateSession($request); + $this->tokenStorage->setToken($token); if (null !== $this->dispatcher) { @@ -114,4 +117,16 @@ private function clearToken(AuthenticationException $exception) * @return array An array composed of the user and the credentials */ abstract protected function getPreAuthenticatedData(Request $request); + + private function migrateSession(Request $request) + { + if (!$request->hasSession() || !$request->hasPreviousSession()) { + return; + } + + // Destroying the old session is broken in php 5.4.0 - 5.4.10 + // See https://bugs.php.net/63379 + $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; + $request->getSession()->migrate($destroy); + } } diff --git a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php index 1ddc41643448e..63bd013c64e31 100644 --- a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Http\Firewall; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; @@ -70,6 +71,9 @@ public function handle(GetResponseEvent $event) try { $token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey)); + + $this->migrateSession($request); + $this->tokenStorage->setToken($token); } catch (AuthenticationException $e) { $token = $this->tokenStorage->getToken(); @@ -88,4 +92,16 @@ public function handle(GetResponseEvent $event) $event->setResponse($this->authenticationEntryPoint->start($request, $e)); } } + + private function migrateSession(Request $request) + { + if (!$request->hasSession() || !$request->hasPreviousSession()) { + return; + } + + // Destroying the old session is broken in php 5.4.0 - 5.4.10 + // See https://bugs.php.net/63379 + $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; + $request->getSession()->migrate($destroy); + } } diff --git a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php index 83ec8b97a490d..5655315a8b0c6 100644 --- a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php @@ -117,6 +117,8 @@ public function handle(GetResponseEvent $event) $this->logger->info('Digest authentication successful.', array('username' => $digestAuth->getUsername(), 'received' => $digestAuth->getResponse())); } + $this->migrateSession($request); + $this->tokenStorage->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey)); } @@ -133,6 +135,18 @@ private function fail(GetResponseEvent $event, Request $request, AuthenticationE $event->setResponse($this->authenticationEntryPoint->start($request, $authException)); } + + private function migrateSession(Request $request) + { + if (!$request->hasSession() || !$request->hasPreviousSession()) { + return; + } + + // Destroying the old session is broken in php 5.4.0 - 5.4.10 + // See https://bugs.php.net/63379 + $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; + $request->getSession()->migrate($destroy); + } } class DigestData diff --git a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php index dd51869405547..23e517969f4e5 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Http\Firewall; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -85,6 +86,9 @@ public function handle(GetResponseEvent $event) } $token = $this->authenticationManager->authenticate($token); + + $this->migrateSession($request); + $this->tokenStorage->setToken($token); if (null !== $this->dispatcher) { @@ -119,4 +123,16 @@ public function handle(GetResponseEvent $event) } } } + + private function migrateSession(Request $request) + { + if (!$request->hasSession() || !$request->hasPreviousSession()) { + return; + } + + // Destroying the old session is broken in php 5.4.0 - 5.4.10 + // See https://bugs.php.net/63379 + $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; + $request->getSession()->migrate($destroy); + } } diff --git a/src/Symfony/Component/Security/Http/Logout/CsrfTokenClearingLogoutHandler.php b/src/Symfony/Component/Security/Http/Logout/CsrfTokenClearingLogoutHandler.php new file mode 100644 index 0000000000000..ad6b888aad562 --- /dev/null +++ b/src/Symfony/Component/Security/Http/Logout/CsrfTokenClearingLogoutHandler.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Http\Logout; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface; + +/** + * @author Christian Flothmann + */ +class CsrfTokenClearingLogoutHandler implements LogoutHandlerInterface +{ + private $csrfTokenStorage; + + public function __construct(ClearableTokenStorageInterface $csrfTokenStorage) + { + $this->csrfTokenStorage = $csrfTokenStorage; + } + + public function logout(Request $request, Response $response, TokenInterface $token) + { + $this->csrfTokenStorage->clear(); + } +} diff --git a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php index b431289392561..15e9b24bb9771 100644 --- a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php +++ b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php @@ -47,8 +47,11 @@ public function onAuthentication(Request $request, TokenInterface $token) return; case self::MIGRATE: + // Note: this logic is duplicated in several authentication listeners + // until Symfony 5.0 due to a security fix with BC compat + // Destroying the old session is broken in php 5.4.0 - 5.4.10 - // See php bug #63379 + // See https://bugs.php.net/63379 $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; $request->getSession()->migrate($destroy); diff --git a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php index 9b05f151340ee..8de89b1868d16 100644 --- a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php +++ b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategyInterface.php @@ -27,8 +27,8 @@ interface SessionAuthenticationStrategyInterface /** * This performs any necessary changes to the session. * - * This method is called before the TokenStorage is populated with a - * Token, and only by classes inheriting from AbstractAuthenticationListener. + * This method should be called before the TokenStorage is populated with a + * Token. It should be used by authentication listeners when a session is used. */ public function onAuthentication(Request $request, TokenInterface $token); } diff --git a/src/Symfony/Component/Security/Http/Tests/Logout/CsrfTokenClearingLogoutHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Logout/CsrfTokenClearingLogoutHandlerTest.php new file mode 100644 index 0000000000000..fe34eaa6e5da3 --- /dev/null +++ b/src/Symfony/Component/Security/Http/Tests/Logout/CsrfTokenClearingLogoutHandlerTest.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Http\Tests\Logout; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; +use Symfony\Component\Security\Http\Logout\CsrfTokenClearingLogoutHandler; + +class CsrfTokenClearingLogoutHandlerTest extends TestCase +{ + private $session; + private $csrfTokenStorage; + private $csrfTokenClearingLogoutHandler; + + protected function setUp() + { + $this->session = new Session(new MockArraySessionStorage()); + $this->csrfTokenStorage = new SessionTokenStorage($this->session, 'foo'); + $this->csrfTokenStorage->setToken('foo', 'bar'); + $this->csrfTokenStorage->setToken('foobar', 'baz'); + $this->csrfTokenClearingLogoutHandler = new CsrfTokenClearingLogoutHandler($this->csrfTokenStorage); + } + + public function testCsrfTokenCookieWithSameNamespaceIsRemoved() + { + $this->assertSame('bar', $this->session->get('foo/foo')); + $this->assertSame('baz', $this->session->get('foo/foobar')); + + $this->csrfTokenClearingLogoutHandler->logout(new Request(), new Response(), $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()); + + $this->assertFalse($this->csrfTokenStorage->hasToken('foo')); + $this->assertFalse($this->csrfTokenStorage->hasToken('foobar')); + + $this->assertFalse($this->session->has('foo/foo')); + $this->assertFalse($this->session->has('foo/foobar')); + } + + public function testCsrfTokenCookieWithDifferentNamespaceIsNotRemoved() + { + $barNamespaceCsrfSessionStorage = new SessionTokenStorage($this->session, 'bar'); + $barNamespaceCsrfSessionStorage->setToken('foo', 'bar'); + $barNamespaceCsrfSessionStorage->setToken('foobar', 'baz'); + + $this->assertSame('bar', $this->session->get('foo/foo')); + $this->assertSame('baz', $this->session->get('foo/foobar')); + $this->assertSame('bar', $this->session->get('bar/foo')); + $this->assertSame('baz', $this->session->get('bar/foobar')); + + $this->csrfTokenClearingLogoutHandler->logout(new Request(), new Response(), $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()); + + $this->assertTrue($barNamespaceCsrfSessionStorage->hasToken('foo')); + $this->assertTrue($barNamespaceCsrfSessionStorage->hasToken('foobar')); + $this->assertSame('bar', $barNamespaceCsrfSessionStorage->getToken('foo')); + $this->assertSame('baz', $barNamespaceCsrfSessionStorage->getToken('foobar')); + $this->assertFalse($this->csrfTokenStorage->hasToken('foo')); + $this->assertFalse($this->csrfTokenStorage->hasToken('foobar')); + + $this->assertFalse($this->session->has('foo/foo')); + $this->assertFalse($this->session->has('foo/foobar')); + $this->assertSame('bar', $this->session->get('bar/foo')); + $this->assertSame('baz', $this->session->get('bar/foobar')); + } +} diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index a604766c0002f..c3e4da18b5b83 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -27,9 +27,12 @@ }, "require-dev": { "symfony/routing": "~2.2|~3.0.0", - "symfony/security-csrf": "^2.8.31|^3.3.13", + "symfony/security-csrf": "^2.8.41|^3.3.17", "psr/log": "~1.0" }, + "conflict": { + "symfony/security-csrf": ">=2.8.0,<2.8.41 || >=3.0.0,<3.3.17 || >=3.4.0,<3.4.11" + }, "suggest": { "symfony/security-csrf": "For using tokens to protect authentication/logout attempts", "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy