Write session data to single key
This prevents decrypting values multiple times.
This commit is contained in:
parent
bfa26db472
commit
e579dd62fd
2 changed files with 34 additions and 20 deletions
|
@ -32,22 +32,38 @@ use OCP\Security\ICrypto;
|
|||
class CryptoSessionData implements \ArrayAccess, ISession {
|
||||
/** @var ISession */
|
||||
protected $session;
|
||||
|
||||
/** @var \OCP\Security\ICrypto */
|
||||
protected $crypto;
|
||||
|
||||
/** @var string */
|
||||
protected $passphrase;
|
||||
/** @var array */
|
||||
protected $sessionValues;
|
||||
CONST encryptedSessionName = 'encrypted_session_data';
|
||||
|
||||
/**
|
||||
* @param ISession $session
|
||||
* @param ICrypto $crypto
|
||||
* @param string $passphrase
|
||||
*/
|
||||
public function __construct(ISession $session, ICrypto $crypto, $passphrase) {
|
||||
public function __construct(ISession $session,
|
||||
ICrypto $crypto,
|
||||
$passphrase) {
|
||||
$this->crypto = $crypto;
|
||||
$this->session = $session;
|
||||
$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
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
$encryptedValue = $this->crypto->encrypt(json_encode($value), $this->passphrase);
|
||||
$this->session->set($key, $encryptedValue);
|
||||
$this->sessionValues[$key] = $value;
|
||||
$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
|
||||
*/
|
||||
public function get($key) {
|
||||
$encryptedValue = $this->session->get($key);
|
||||
if ($encryptedValue === null) {
|
||||
return null;
|
||||
|
||||
if(isset($this->sessionValues[$key])) {
|
||||
return $this->sessionValues[$key];
|
||||
}
|
||||
|
||||
try {
|
||||
$value = $this->crypto->decrypt($encryptedValue, $this->passphrase);
|
||||
return json_decode($value);
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,7 +100,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
|
|||
* @return bool
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public function remove($key) {
|
||||
$this->session->remove($key);
|
||||
unset($this->sessionValues[$key]);
|
||||
$this->session->remove(self::encryptedSessionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset and recreate the session
|
||||
*/
|
||||
public function clear() {
|
||||
$this->sessionValues = [];
|
||||
$this->session->clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ class CryptoWrappingTest extends TestCase {
|
|||
|
||||
$this->wrappedSession->expects($this->once())
|
||||
->method('set')
|
||||
->with('key', $this->crypto->encrypt(json_encode($unencryptedValue)));
|
||||
$this->instance->set('key', $unencryptedValue);
|
||||
->with('encrypted_session_data', $this->crypto->encrypt(json_encode(['encrypted_session_data' => $unencryptedValue])));
|
||||
$this->instance->set('encrypted_session_data', $unencryptedValue);
|
||||
}
|
||||
|
||||
public function testUnwrappingGet() {
|
||||
|
@ -72,11 +72,11 @@ class CryptoWrappingTest extends TestCase {
|
|||
|
||||
$this->wrappedSession->expects($this->once())
|
||||
->method('get')
|
||||
->with('key')
|
||||
->with('encrypted_session_data')
|
||||
->willReturnCallback(function () use ($encryptedValue) {
|
||||
return $encryptedValue;
|
||||
});
|
||||
|
||||
$this->assertSame($unencryptedValue, $this->wrappedSession->get('key'));
|
||||
$this->assertSame($unencryptedValue, $this->wrappedSession->get('encrypted_session_data'));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue