diff options
Diffstat (limited to 'framework/Web/UI/TPageStatePersister.php')
-rw-r--r-- | framework/Web/UI/TPageStatePersister.php | 116 |
1 files changed, 35 insertions, 81 deletions
diff --git a/framework/Web/UI/TPageStatePersister.php b/framework/Web/UI/TPageStatePersister.php index 4ece9a09..746d93c8 100644 --- a/framework/Web/UI/TPageStatePersister.php +++ b/framework/Web/UI/TPageStatePersister.php @@ -14,36 +14,38 @@ * TPageStatePersister class
*
* TPageStatePersister implements a page state persistent method based on
- * form hidden fields. It is the default way of storing page state.
- * Should you need to access this module, you may get it via
- * {@link TPageService::getPageStatePersister}.
+ * form hidden fields.
*
- * TPageStatePersister uses a private key to generate a private unique hash
- * code to prevent the page state from being tampered.
- * By default, the private key is a randomly generated string.
- * You may specify it explicitly by setting the {@link setPrivateKey PrivateKey} property.
- * This may be useful if your application is running on a server farm.
+ * Depending on the {@link TPage::getEnableStateHMAC() EnableStateHMAC}
+ * and {@link TPage::getEnableStateEncryption() EnableStateEncryption},
+ * TPageStatePersister may do HMAC validation and encryption to prevent
+ * the state data from being tampered or viewed.
+ * The private keys and hashing/encryption methods are determined by
+ * {@link TApplication::getSecurityManager() SecurityManager}.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Revision: $ $Date: $
* @package System.Web.UI
* @since 3.0
*/
-class TPageStatePersister extends TModule implements IStatePersister
+class TPageStatePersister extends TComponent implements IPageStatePersister
{
+ private $_page;
+
/**
- * @var string private key
+ * @param TPage the page that this persister works for
*/
- private $_privateKey=null;
+ public function getPage()
+ {
+ return $this->_page;
+ }
/**
- * Registers the module with the page service.
- * This method is required by IModule interface and is invoked when the module is initialized.
- * @param TXmlElement module configuration
+ * @param TPage the page that this persister works for
*/
- public function init($config)
+ public function setPage(TPage $page)
{
- $this->getService()->setPageStatePersister($this);
+ $this->_page=$page;
}
/**
@@ -53,13 +55,15 @@ class TPageStatePersister extends TModule implements IStatePersister public function save($state)
{
Prado::trace("Saving state",'System.Web.UI.TPageStatePersister');
- $data=Prado::serialize($state);
- $hmac=$this->computeHMAC($data,$this->getPrivateKey());
- if(extension_loaded('zlib'))
- $data=gzcompress($hmac.$data);
+ if($this->_page->getEnableStateHMAC())
+ $data=$this->getApplication()->getSecurityManager()->hashData(Prado::serialize($state));
else
- $data=$hmac.$data;
- $this->getService()->getRequestedPage()->getClientScript()->registerHiddenField(TPage::FIELD_PAGESTATE,base64_encode($data));
+ $data=Prado::serialize($state);
+ if($this->_page->getEnableStateEncryption())
+ $data=$this->getApplication()->getSecurityManager()->encrypt($data);
+ if(extension_loaded('zlib'))
+ $data=gzcompress($data);
+ $this->_page->getClientScript()->registerHiddenField(TPage::FIELD_PAGESTATE,base64_encode($data));
}
/**
@@ -77,69 +81,19 @@ class TPageStatePersister extends TModule implements IStatePersister $data=gzuncompress($str);
else
$data=$str;
- if($data!==false && strlen($data)>32)
+ if($data!==false)
{
- $hmac=substr($data,0,32);
- $state=substr($data,32);
- if($hmac===$this->computeHMAC($state,$this->getPrivateKey()))
- return Prado::unserialize($state);
- }
- throw new THttpException(400,'pagestatepersister_pagestate_corrupted');
- }
-
- /**
- * Generates a random private key used for hashing the state.
- * You may override this method to provide your own way of private key generation.
- * @return string the rondomly generated private key
- */
- protected function generatePrivateKey()
- {
- $v1=rand();
- $v2=rand();
- $v3=rand();
- return md5("$v1$v2$v3");
- }
-
- /**
- * @return string private key used for hashing the state.
- */
- public function getPrivateKey()
- {
- if(empty($this->_privateKey))
- {
- if(($this->_privateKey=$this->getApplication()->getGlobalState('prado:pagestatepersister:privatekey'))===null)
+ if($this->_page->getEnableStateEncryption())
+ $data=$this->getApplication()->getSecurityManager()->decrypt($data);
+ if($this->_page->getEnableStateHMAC())
{
- $this->_privateKey=$this->generatePrivateKey();
- $this->getApplication()->setGlobalState('prado:pagestatepersister:privatekey',$this->_privateKey,null);
+ if(($data=$this->getApplication()->getSecurityManager()->validateData($data))!==null)
+ return Prado::unserialize($data);
}
+ else
+ return $data;
}
- return $this->_privateKey;
- }
-
- /**
- * @param string private key used for hashing the state.
- * @throws TInvalidDataValueException if the length of the private key is shorter than 8.
- */
- public function setPrivateKey($value)
- {
- if(strlen($value)<8)
- throw new TInvalidDataValueException('pagestatepersister_privatekey_invalid');
- $this->_privateKey=$value;
- }
-
- /**
- * Computes a hashing code based on the input data and the private key.
- * @param string input data
- * @param string the private key
- * @return string the hashing code
- */
- private function computeHMAC($data,$key)
- {
- if (strlen($key) > 64)
- $key = pack('H32', md5($key));
- else if (strlen($key) < 64)
- $key = str_pad($key, 64, "\0");
- return md5((str_repeat("\x5c", 64) ^ substr($key, 0, 64)) . pack('H32', md5((str_repeat("\x36", 64) ^ substr($key, 0, 64)) . $data)));
+ throw new THttpException(400,'pagestatepersister_pagestate_corrupted');
}
}
|