Merge pull request #18913 from owncloud/put-in-single-field-for-speed

Put session data in single field for speed
This commit is contained in:
Lukas Reschke 2015-09-09 14:10:01 +02:00
commit a05ccd969c
4 changed files with 52 additions and 35 deletions

View File

@ -177,8 +177,6 @@ class Server extends SimpleContainer implements IServerContainer {
$manager = $c->getUserManager(); $manager = $c->getUserManager();
$session = new \OC\Session\Memory(''); $session = new \OC\Session\Memory('');
$cryptoWrapper = $c->getSessionCryptoWrapper();
$session = $cryptoWrapper->wrapSession($session);
$userSession = new \OC\User\Session($manager, $session); $userSession = new \OC\User\Session($manager, $session);
$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) { $userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
@ -252,7 +250,7 @@ class Server extends SimpleContainer implements IServerContainer {
if($config->getSystemValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) { if($config->getSystemValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
$v = \OC_App::getAppVersions(); $v = \OC_App::getAppVersions();
$v['core'] = implode('.', \OC_Util::getVersion()); $v['core'] = md5(file_get_contents(\OC::$SERVERROOT . '/version.php'));
$version = implode(',', $v); $version = implode(',', $v);
$instanceId = \OC_Util::getInstanceId(); $instanceId = \OC_Util::getInstanceId();
$path = \OC::$SERVERROOT; $path = \OC::$SERVERROOT;

View File

@ -32,22 +32,47 @@ 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;
/** @var bool */
protected $isModified = false;
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();
}
/**
* Close session if class gets destructed
*/
public function __destruct() {
$this->close();
}
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 +82,8 @@ 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); $this->isModified = true;
} }
/** /**
@ -68,17 +93,11 @@ 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(isset($this->sessionValues[$key])) {
if ($encryptedValue === null) { return $this->sessionValues[$key];
return null;
} }
try { return null;
$value = $this->crypto->decrypt($encryptedValue, $this->passphrase);
return json_decode($value);
} catch (\Exception $e) {
return null;
}
} }
/** /**
@ -88,7 +107,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,20 +116,29 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param string $key * @param string $key
*/ */
public function remove($key) { public function remove($key) {
$this->session->remove($key); $this->isModified = true;
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->isModified = true;
$this->session->clear(); $this->session->clear();
} }
/** /**
* Close the session and release the lock * Close the session and release the lock, also writes all changed data in batch
*/ */
public function close() { public function close() {
if($this->isModified) {
$encryptedValue = $this->crypto->encrypt(json_encode($this->sessionValues), $this->passphrase);
$this->session->set(self::encryptedSessionName, $encryptedValue);
$this->isModified = false;
}
$this->session->close(); $this->session->close();
} }

View File

@ -32,6 +32,10 @@ namespace OC\Session;
* @package OC\Session * @package OC\Session
*/ */
class Internal extends Session { class Internal extends Session {
/**
* @param string $name
* @throws \Exception
*/
public function __construct($name) { public function __construct($name) {
session_name($name); session_name($name);
set_error_handler(array($this, 'trapError')); set_error_handler(array($this, 'trapError'));
@ -42,10 +46,6 @@ class Internal extends Session {
} }
} }
public function __destruct() {
$this->close();
}
/** /**
* @param string $key * @param string $key
* @param integer $value * @param integer $value

View File

@ -57,26 +57,17 @@ class CryptoWrappingTest extends TestCase {
$this->instance = new CryptoSessionData($this->wrappedSession, $this->crypto, 'PASS'); $this->instance = new CryptoSessionData($this->wrappedSession, $this->crypto, 'PASS');
} }
public function testWrappingSet() {
$unencryptedValue = 'foobar';
$this->wrappedSession->expects($this->once())
->method('set')
->with('key', $this->crypto->encrypt(json_encode($unencryptedValue)));
$this->instance->set('key', $unencryptedValue);
}
public function testUnwrappingGet() { public function testUnwrappingGet() {
$unencryptedValue = 'foobar'; $unencryptedValue = 'foobar';
$encryptedValue = $this->crypto->encrypt($unencryptedValue); $encryptedValue = $this->crypto->encrypt($unencryptedValue);
$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'));
} }
} }