Write session data to single key

This prevents decrypting values multiple times.
This commit is contained in:
Lukas Reschke 2015-09-08 21:16:11 +02:00
parent bfa26db472
commit e579dd62fd
2 changed files with 34 additions and 20 deletions

View File

@ -32,22 +32,38 @@ use OCP\Security\ICrypto;
class CryptoSessionData implements \ArrayAccess, ISession { class CryptoSessionData implements \ArrayAccess, ISession {
/** @var ISession */ /** @var ISession */
protected $session; protected $session;
/** @var \OCP\Security\ICrypto */ /** @var \OCP\Security\ICrypto */
protected $crypto; protected $crypto;
/** @var string */ /** @var string */
protected $passphrase; protected $passphrase;
/** @var array */
protected $sessionValues;
CONST encryptedSessionName = 'encrypted_session_data';
/** /**
* @param ISession $session * @param ISession $session
* @param ICrypto $crypto * @param ICrypto $crypto
* @param string $passphrase * @param string $passphrase
*/ */
public function __construct(ISession $session, ICrypto $crypto, $passphrase) { public function __construct(ISession $session,
ICrypto $crypto,
$passphrase) {
$this->crypto = $crypto; $this->crypto = $crypto;
$this->session = $session; $this->session = $session;
$this->passphrase = $passphrase; $this->passphrase = $passphrase;
$this->initializeSession();
}
protected function initializeSession() {
$encryptedSessionData = $this->session->get(self::encryptedSessionName);
try {
$this->sessionValues = json_decode(
$this->crypto->decrypt($encryptedSessionData, $this->passphrase),
true
);
} catch (\Exception $e) {
$this->sessionValues = [];
}
} }
/** /**
@ -57,8 +73,9 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param mixed $value * @param mixed $value
*/ */
public function set($key, $value) { public function set($key, $value) {
$encryptedValue = $this->crypto->encrypt(json_encode($value), $this->passphrase); $this->sessionValues[$key] = $value;
$this->session->set($key, $encryptedValue); $encryptedValue = $this->crypto->encrypt(json_encode($this->sessionValues), $this->passphrase);
$this->session->set(self::encryptedSessionName, $encryptedValue);
} }
/** /**
@ -68,17 +85,12 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @return string|null Either the value or null * @return string|null Either the value or null
*/ */
public function get($key) { public function get($key) {
$encryptedValue = $this->session->get($key);
if ($encryptedValue === null) { if(isset($this->sessionValues[$key])) {
return null; return $this->sessionValues[$key];
} }
try { return null;
$value = $this->crypto->decrypt($encryptedValue, $this->passphrase);
return json_decode($value);
} catch (\Exception $e) {
return null;
}
} }
/** /**
@ -88,7 +100,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @return bool * @return bool
*/ */
public function exists($key) { public function exists($key) {
return $this->session->exists($key); return isset($this->sessionValues[$key]);
} }
/** /**
@ -97,13 +109,15 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param string $key * @param string $key
*/ */
public function remove($key) { public function remove($key) {
$this->session->remove($key); unset($this->sessionValues[$key]);
$this->session->remove(self::encryptedSessionName);
} }
/** /**
* Reset and recreate the session * Reset and recreate the session
*/ */
public function clear() { public function clear() {
$this->sessionValues = [];
$this->session->clear(); $this->session->clear();
} }

View File

@ -62,8 +62,8 @@ class CryptoWrappingTest extends TestCase {
$this->wrappedSession->expects($this->once()) $this->wrappedSession->expects($this->once())
->method('set') ->method('set')
->with('key', $this->crypto->encrypt(json_encode($unencryptedValue))); ->with('encrypted_session_data', $this->crypto->encrypt(json_encode(['encrypted_session_data' => $unencryptedValue])));
$this->instance->set('key', $unencryptedValue); $this->instance->set('encrypted_session_data', $unencryptedValue);
} }
public function testUnwrappingGet() { public function testUnwrappingGet() {
@ -72,11 +72,11 @@ class CryptoWrappingTest extends TestCase {
$this->wrappedSession->expects($this->once()) $this->wrappedSession->expects($this->once())
->method('get') ->method('get')
->with('key') ->with('encrypted_session_data')
->willReturnCallback(function () use ($encryptedValue) { ->willReturnCallback(function () use ($encryptedValue) {
return $encryptedValue; return $encryptedValue;
}); });
$this->assertSame($unencryptedValue, $this->wrappedSession->get('key')); $this->assertSame($unencryptedValue, $this->wrappedSession->get('encrypted_session_data'));
} }
} }