Compare commits
16 commits
aaacd95a06
...
9e3d1fd2ac
Author | SHA1 | Date | |
---|---|---|---|
9e3d1fd2ac | |||
aa150cea9f | |||
287ef82621 | |||
9f30b80d39 | |||
7c13ff8e71 | |||
0ae4ab9269 | |||
28c6c8ef59 | |||
d7dbff9fc2 | |||
e58a157037 | |||
5d8e93084b | |||
4dfb3b8568 | |||
7306320814 | |||
5ed22d20f0 | |||
d3714249e5 | |||
abfb8332b3 | |||
f7914f7a4b |
6 changed files with 52 additions and 30 deletions
7
.woodpecker/code-style.yml
Normal file
7
.woodpecker/code-style.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
pipeline:
|
||||
code-style:
|
||||
image: composer
|
||||
commands:
|
||||
- composer global config repositories.repo-name vcs https://git.digital-competence.de/Packages/php-codesniffer
|
||||
- composer global require digicomp/php-codesniffer:@dev
|
||||
- composer global exec -- phpcs --runtime-set ignore_warnings_on_exit 1 --standard=DigiComp Classes/ Tests/
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace DigiComp\FlowSessionLock\Aspects;
|
||||
|
||||
use DigiComp\FlowSessionLock\Http\SessionLockRequestComponent;
|
||||
use DigiComp\FlowSessionLock\Http\SessionLockRequestMiddleware;
|
||||
use Neos\Flow\Annotations as Flow;
|
||||
use Neos\Flow\Aop\JoinPointInterface;
|
||||
use Neos\Flow\Core\Bootstrap;
|
||||
|
@ -52,9 +52,8 @@ class ReadOnlyAspect
|
|||
$this->readOnly = true;
|
||||
|
||||
/** @var Lock|null $lock */
|
||||
$lock = $activeRequestHandler->getComponentContext()->getParameter(
|
||||
SessionLockRequestComponent::class,
|
||||
SessionLockRequestComponent::PARAMETER_NAME
|
||||
$lock = $activeRequestHandler->getHttpRequest()->getAttribute(
|
||||
SessionLockRequestMiddleware::class . '.' . SessionLockRequestMiddleware::PARAMETER_NAME
|
||||
);
|
||||
if ($lock !== null) {
|
||||
$this->logger->debug('SessionLock: Release, as this is marked read only.');
|
||||
|
|
|
@ -5,14 +5,16 @@ declare(strict_types=1);
|
|||
namespace DigiComp\FlowSessionLock\Http;
|
||||
|
||||
use Neos\Flow\Annotations as Flow;
|
||||
use Neos\Flow\Http\Component\ComponentContext;
|
||||
use Neos\Flow\Http\Component\ComponentInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Lock\Exception\LockAcquiringException;
|
||||
use Symfony\Component\Lock\Key;
|
||||
use Symfony\Component\Lock\LockFactory;
|
||||
|
||||
class SessionLockRequestComponent implements ComponentInterface
|
||||
class SessionLockRequestMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public const PARAMETER_NAME = 'sessionLock';
|
||||
|
||||
|
@ -55,13 +57,13 @@ class SessionLockRequestComponent implements ComponentInterface
|
|||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function handle(ComponentContext $componentContext): void
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
$sessionCookieName = $this->sessionSettings['name'];
|
||||
|
||||
$cookies = $componentContext->getHttpRequest()->getCookieParams();
|
||||
$cookies = $request->getCookieParams();
|
||||
if (!isset($cookies[$sessionCookieName])) {
|
||||
return;
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
||||
// TODO: sessionIdentifier might be wrong, probably it should probably be storage identifier
|
||||
|
@ -69,7 +71,7 @@ class SessionLockRequestComponent implements ComponentInterface
|
|||
|
||||
$lock = $this->lockFactory->createLockFromKey($key, $this->timeToLive, $this->autoRelease);
|
||||
|
||||
$componentContext->setParameter(SessionLockRequestComponent::class, static::PARAMETER_NAME, $lock);
|
||||
$request = $request->withAttribute(SessionLockRequestMiddleware::class . '.' . static::PARAMETER_NAME, $lock);
|
||||
|
||||
$this->logger->debug('SessionLock: Try to get "' . $key . '"');
|
||||
$timedOut = \time() + $this->secondsToWait;
|
||||
|
@ -83,5 +85,6 @@ class SessionLockRequestComponent implements ComponentInterface
|
|||
\usleep(100000);
|
||||
}
|
||||
$this->logger->debug('SessionLock: Acquired "' . $key . '"');
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
|
@ -9,9 +9,7 @@ DigiComp:
|
|||
Neos:
|
||||
Flow:
|
||||
http:
|
||||
chain:
|
||||
preprocess:
|
||||
chain:
|
||||
middlewares:
|
||||
lockSession:
|
||||
position: "before getSessionCookieFromRequest"
|
||||
component: "DigiComp\\FlowSessionLock\\Http\\SessionLockRequestComponent"
|
||||
position: "before session"
|
||||
middleware: "DigiComp\\FlowSessionLock\\Http\\SessionLockRequestMiddleware"
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace DigiComp\FlowSessionLock\Tests\Functional;
|
|||
|
||||
use DigiComp\FlowSessionLock\Tests\Functional\Fixtures\Controller\ExampleController;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Neos\Flow\Composer\ComposerUtility;
|
||||
use Neos\Flow\Http\Cookie;
|
||||
use Neos\Flow\Mvc\Routing\Route;
|
||||
use Neos\Flow\Tests\FunctionalTestCase;
|
||||
|
@ -43,16 +44,16 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
|
|||
function ($allRequests, $oneRequest) {
|
||||
self::assertGreaterThan(ExampleController::CONTROLLER_TIME, $oneRequest * 1000);
|
||||
self::assertGreaterThan(ExampleController::CONTROLLER_TIME * 4, $allRequests * 1000);
|
||||
}
|
||||
},
|
||||
],
|
||||
[
|
||||
'http://localhost/test/sessionlock/unprotectedbyannotation',
|
||||
$parallelChecker
|
||||
$parallelChecker,
|
||||
],
|
||||
[
|
||||
'http://localhost/test/sessionlock/unprotectedbyconfiguration',
|
||||
$parallelChecker
|
||||
]
|
||||
$parallelChecker,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -62,18 +63,21 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
|
|||
*/
|
||||
public function itDoesNotAllowToEnterMoreThanOneWithTheSameSession(string $url, \Closure $checker): void
|
||||
{
|
||||
// Functional tests are currently broken, until a version containing
|
||||
// https://github.com/neos/flow-development-collection/commit/bebfc4e6566bc4ba2ba28330344105adb2d6ada0
|
||||
// gets released
|
||||
$request = $this->serverRequestFactory
|
||||
->createServerRequest('GET', new Uri($url));
|
||||
$start = microtime(true);
|
||||
$start = \microtime(true);
|
||||
$response = $this->browser->sendRequest($request);
|
||||
$neededForOne = microtime(true) - $start;
|
||||
$neededForOne = \microtime(true) - $start;
|
||||
|
||||
$sessionCookies = array_map(static function ($cookie) {
|
||||
$sessionCookies = \array_map(static function ($cookie) {
|
||||
return Cookie::createFromRawSetCookieHeader($cookie);
|
||||
}, $response->getHeader('Set-Cookie'));
|
||||
self::assertNotEmpty($sessionCookies);
|
||||
|
||||
$cookies = array_reduce($sessionCookies, static function ($out, $cookie) {
|
||||
$cookies = \array_reduce($sessionCookies, static function ($out, $cookie) {
|
||||
$out[$cookie->getName()] = $cookie->getValue();
|
||||
return $out;
|
||||
}, []);
|
||||
|
@ -81,7 +85,7 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
|
|||
->createServerRequest('GET', new Uri($url))
|
||||
->withCookieParams($cookies);
|
||||
$childs = [];
|
||||
$start = microtime(true);
|
||||
$start = \microtime(true);
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
$child = \pcntl_fork();
|
||||
if ($child === 0) {
|
||||
|
@ -93,7 +97,7 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
|
|||
foreach ($childs as $child) {
|
||||
\pcntl_waitpid($child, $status);
|
||||
}
|
||||
$neededForAll = microtime(true) - $start;
|
||||
$neededForAll = \microtime(true) - $start;
|
||||
|
||||
$checker($neededForAll, $neededForOne);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"description": "Session locking for Neos Flow - it secures the session becoming corrupted by concurrent access to the same session by different requests",
|
||||
"type": "neos-package",
|
||||
"require": {
|
||||
"neos/flow": "^6.3.0",
|
||||
"neos/flow": "^7.3.0",
|
||||
"php": ">=7.4",
|
||||
"symfony/lock": "^5.2.0"
|
||||
},
|
||||
|
@ -20,8 +20,19 @@
|
|||
"package-key": "DigiComp.FlowSessionLock"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-develop": "2.0.x-dev"
|
||||
}
|
||||
"dev-develop": "3.0.x-dev"
|
||||
},
|
||||
"applied-flow-migrations": [
|
||||
"Neos.SwiftMailer-20161130105617",
|
||||
"Neos.Flow-20180415105700",
|
||||
"Neos.Flow-20190425144900",
|
||||
"Neos.Flow-20190515215000",
|
||||
"Neos.Flow-20200813181400",
|
||||
"Neos.Flow-20201003165200",
|
||||
"Neos.Flow-20201109224100",
|
||||
"Neos.Flow-20201205172733",
|
||||
"Neos.Flow-20201207104500"
|
||||
]
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue