zend form 防止重复提交

zend form ,我们常用它的表单检查和大规模创建表单操作,但是好像它并没有给出防止表单重复提交的方案,除了在页面上做脚本(js)锁定操作的方案外,我们还要在服务器端做更加安全的检查。

下面介绍一下我的方案:

利用session(或缓存)和form token来防止表单的重复提交。核心是一个表单基类和一个validator。

表单基类:

<?php
/**
 * 表单基类,负责添加表单令牌。
 * @author Ju <hipop@126.com>
 *
 */
class Application_Form_Base extends Zend_Form
{
	const TOKEN_ID = "__form_token__";

    public function init()
    {
        $tokenElement = $this->createElement('hidden',self::TOKEN_ID);
        $tokenElement->addValidator("Formtoken")
        			 ->setRequired(TRUE)
        			 ->setValue($this->getTokenVal())
        			 ->addPrefixPath("Application_Validate",APPLICATION_PATH."/plugins/validators/","VALIDATE");
        $this->addElement($tokenElement);
    }
	
    private function getTokenVal(){
    	return  md5(time());
    }
    
    public function getToken(){
    	return $this->getElement(self::TOKEN_ID)->getValue();
    }
    
    /**
     * 返回令牌错误,包装msg方法,方便使用
     * @return string
     */
    public function getTokenError(){
    	return $this->getMessages(self::TOKEN_ID);
    }

}


插件:

<?php
/**
 * 维护表单提交的token队列
 * @author Ju <hipop@126.com>
 *
 */
class Application_Validate_Formtoken extends Zend_Validate_Abstract
{
	const NOT_MATCH = 'doNotResubmit';

    protected $_messageTemplates = array(
        self::NOT_MATCH => '请不要重复提交表单!'
    );
	
	
	private $_listLength = 10; 
	private $_tokenList; //固定长度数组
	private $_sessionTokenLst;
	
	public function __construct(){
		Zend_Session::start();
		$this->_sessionTokenLst = new Zend_Session_Namespace("FORMTOKENLST"); 
		$this->_getTokenList();
	}
	
	/**
	 * 从session中获取token队列
	 * Enter description here ...
	 */
	private function _getTokenList(){
		$this->_tokenList = $this->_sessionTokenLst->TOKENLIST;
		$this->_tokenList = is_array($this->_tokenList)?$this->_tokenList:array();
	}
	
	/**
	 * 将队列放入session
	 * Enter description here ...
	 * @param array $tokenlist
	 */
	private function _setTokenList($tokenlist=NULL){
		$tokenlist = is_array($tokenlist)?$tokenlist:array();
		if(count($tokenlist)>$this->_listLength){
			array_shift($tokenlist);
			return $this->_setTokenList($tokenlist);
		}
		$this->_sessionTokenLst->TOKENLIST = $tokenlist;
	}
	
	/**
	 * 检查token
	 * Enter description here ...
	 * @param string $token
	 * @return boolean
	 */
	public function check($token){
		if (in_array($token,$this->_tokenList)){
			$this->_error(self::NOT_MATCH);
			return FALSE;	
		}else {
			array_push($this->_tokenList ,$token);
			$this->_setTokenList($this->_tokenList);
			return TRUE;
		}
	}
	
	/* (non-PHPdoc)
	 * @see Zend_Validate_Interface::isValid()
	 */
	public function isValid($value) {
		// TODO Auto-generated method stub
		return $this->check($value);
	}

}

使用的时候,表单要继承基类,并调用父类 的初始化方法。然后再isValid就ok了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值