diff options
Diffstat (limited to 'framework/Web')
-rw-r--r-- | framework/Web/Services/TPageService.php | 26 | ||||
-rw-r--r-- | framework/Web/UI/TPage.php | 81 | ||||
-rw-r--r-- | framework/Web/UI/TPageStatePersister.php | 116 |
3 files changed, 106 insertions, 117 deletions
diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php index 463f2dec..393194a1 100644 --- a/framework/Web/Services/TPageService.php +++ b/framework/Web/Services/TPageService.php @@ -17,7 +17,6 @@ Prado::using('System.Web.UI.TPage'); Prado::using('System.Web.UI.TTemplateManager');
Prado::using('System.Web.UI.TThemeManager');
Prado::using('System.Web.UI.TAssetManager');
-Prado::using('System.Web.UI.TPageStatePersister');
/**
* TPageService class.
@@ -134,10 +133,6 @@ class TPageService extends TService * @var TTemplateManager template manager
*/
private $_templateManager=null;
- /**
- * @var IStatePersister page state persister
- */
- private $_pageStatePersister=null;
/**
* Initializes the service.
@@ -344,27 +339,6 @@ class TPageService extends TService }
/**
- * @return IStatePersister page state persister
- */
- public function getPageStatePersister()
- {
- if(!$this->_pageStatePersister)
- {
- $this->_pageStatePersister=new TPageStatePersister;
- $this->_pageStatePersister->init(null);
- }
- return $this->_pageStatePersister;
- }
-
- /**
- * @param IStatePersister page state persister
- */
- public function setPageStatePersister(IStatePersister $value)
- {
- $this->_pageStatePersister=$value;
- }
-
- /**
* @return string the requested page path
*/
public function getRequestedPagePath()
diff --git a/framework/Web/UI/TPage.php b/framework/Web/UI/TPage.php index 11f89ab5..78d9115e 100644 --- a/framework/Web/UI/TPage.php +++ b/framework/Web/UI/TPage.php @@ -129,6 +129,11 @@ class TPage extends TTemplateControl private $_isCrossPagePostBack=false;
private $_previousPagePath='';
+ private $_statePersisterClass='System.Web.UI.TPageStatePersister';
+ private $_statePersister=null;
+ private $_enableStateHMAC=true;
+ private $_enableStateEncryption=false;
+
/**
* Constructor.
* Sets the page object to itself.
@@ -514,14 +519,6 @@ class TPage extends TTemplateControl }
/**
- * @return IStatePersister page state persister
- */
- protected function getPageStatePersister()
- {
- return $this->getService()->getPageStatePersister();
- }
-
- /**
* This method is invoked when control state is to be saved.
* You can override this method to do last step state saving.
* Parent implementation must be invoked.
@@ -548,7 +545,7 @@ class TPage extends TTemplateControl */
protected function loadPageState()
{
- $state=$this->getPageStatePersister()->load();
+ $state=$this->getStatePersister()->load();
$this->loadStateRecursive($state,$this->getEnableViewState());
}
@@ -558,7 +555,7 @@ class TPage extends TTemplateControl protected function savePageState()
{
$state=&$this->saveStateRecursive($this->getEnableViewState());
- $this->getPageStatePersister()->save($state);
+ $this->getStatePersister()->save($state);
}
/**
@@ -806,6 +803,70 @@ class TPage extends TTemplateControl {
$this->setViewState('Title',$value,'');
}
+
+ public function getStatePersisterClass()
+ {
+ return $this->_statePersisterClass;
+ }
+
+ public function setStatePersisterClass($value)
+ {
+ $this->_statePersisterClass=$value;
+ }
+
+ public function getStatePersister()
+ {
+ if($this->_statePersister===null)
+ {
+ $this->_statePersister=Prado::createComponent($this->_statePersisterClass);
+ if(!($this->_statePersister instanceof IPageStatePersister))
+ throw new TInvalidDataTypeException('page_statepersister_invalid');
+ $this->_statePersister->setPage($this);
+ }
+ return $this->_statePersister;
+ }
+
+ public function getEnableStateHMAC()
+ {
+ return $this->_enableStateHMAC;
+ }
+
+ public function setEnableStateHMAC($value)
+ {
+ $this->_enableStateHMAC=TPropertyValue::ensureBoolean($value);
+ }
+
+ public function getEnableStateEncryption()
+ {
+ return $this->_enableStateEncryption;
+ }
+
+ public function setEnableStateEncryption($value)
+ {
+ $this->_enableStateEncryption=TPropertyValue::ensureBoolean($value);
+ }
+}
+
+interface IPageStatePersister
+{
+ /**
+ * @param TPage the page that this persister works for
+ */
+ public function getPage();
+ /**
+ * @param TPage the page that this persister works for
+ */
+ public function setPage(TPage $page);
+ /**
+ * Saves state to persistent storage.
+ * @param string state to be stored
+ */
+ public function save($state);
+ /**
+ * Loads page state from persistent storage
+ * @return string the restored state
+ */
+ public function load();
}
?>
\ No newline at end of file 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');
}
}
|