From c0aa5200f7a2a0cf8698d3f47e98f8bead9eef52 Mon Sep 17 00:00:00 2001 From: Joe Lambert Date: Wed, 4 Oct 2023 09:18:33 +0100 Subject: [PATCH] Gracefully handle encryption errors in session --- src/Session/EncryptedStore.php | 15 +++++++++--- tests/Unit/Session/EncryptedStoreTest.php | 30 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Session/EncryptedStore.php b/src/Session/EncryptedStore.php index e731f1e..3a35953 100644 --- a/src/Session/EncryptedStore.php +++ b/src/Session/EncryptedStore.php @@ -2,16 +2,20 @@ namespace Rareloop\Lumberjack\Session; -use Rareloop\Lumberjack\Encrypter; +use Exception; use SessionHandlerInterface; +use Rareloop\Lumberjack\Encrypter; +use Rareloop\Lumberjack\Exceptions\HandlerInterface; class EncryptedStore extends Store { protected $encrypter; + protected $exceptionHandler; - public function __construct($name, SessionHandlerInterface $handler, Encrypter $encrypter, $id = null) + public function __construct($name, SessionHandlerInterface $handler, Encrypter $encrypter, $id = null, HandlerInterface $exceptionHandler = null) { $this->encrypter = $encrypter; + $this->exceptionHandler = $exceptionHandler; parent::__construct($name, $handler, $id); } @@ -23,6 +27,11 @@ protected function prepareForStorage($data) protected function prepareForUnserialize($data) { - return $this->encrypter->decrypt($data); + try { + return $this->encrypter->decrypt($data); + } catch (Exception $e) { + $this->exceptionHandler->report($e); + return null; + } } } diff --git a/tests/Unit/Session/EncryptedStoreTest.php b/tests/Unit/Session/EncryptedStoreTest.php index 5d80a46..fb2a324 100644 --- a/tests/Unit/Session/EncryptedStoreTest.php +++ b/tests/Unit/Session/EncryptedStoreTest.php @@ -6,6 +6,7 @@ use Mockery; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Encrypter; +use Rareloop\Lumberjack\Exceptions\HandlerInterface; use Rareloop\Lumberjack\Session\EncryptedStore; use Rareloop\Lumberjack\Session\Store; use Rareloop\Lumberjack\Test\Unit\Session\NullSessionHandler; @@ -50,4 +51,33 @@ public function data_is_decrypted_before_it_is_loaded() $this->assertSame('bar', $store->get('foo')); } + + /** + * @test + * @dataProvider unexpectedSessionData + */ + public function unexpected_session_data_is_handled_gracefully($previousSessionValue) + { + $encryptionKey = 'encryption-key'; + + // Use a mock handler to fake a previously stored state + $handler = Mockery::mock(NullSessionHandler::class . '[read]'); + $handler->shouldReceive('read')->andReturn($previousSessionValue); + + $errorHandler = Mockery::mock(HandlerInterface::class); + $errorHandler->shouldReceive('report')->once(); + + $store = new EncryptedStore('session-name', $handler, new Encrypter($encryptionKey), 'session-id', $errorHandler); + $store->start(); + + $this->assertSame(null, $store->get('foo')); + } + + private function unexpectedSessionData() + { + return [ + [@serialize(['foo' => 'bar'])], + [''], + ]; + } }