YII 局部CSRF、令牌使用sessio存儲

YII 自帶的CSRF功能很強大,每個form提交的數都會進行令牌驗證,導致在接收支付寶同步通知時,被YII的CSRF功能擋之門外。項目中可能有些地方需要進行CSRF驗證,但是有些地方又不需要。YII2在頂級控制器中添加了關閉csrf的一個屬性:
/**
 * @var boolean whether to enable CSRF validation for the actions in this controller.
 * CSRF validation is enabled only when both this property and [[Request::enableCsrfValidation]] are true.
*/
 public $enableCsrfValidation = true;

但是yii2.0以下的版本是沒有這個屬性的。這是就得重寫HttpRequest組件了。

<?php
class HttpRequest extends CHttpRequest{

    public $noCsrfValidationRoutes=array();

    //將CSRF令牌存入session
    /**
    +----------------------------------------------------------
     * 重寫CHttpRequest中getCsrfToken方法
    +----------------------------------------------------------
     * author   fujia<@.com>
     * time     2015年4月27日20:47:54
    +----------------------------------------------------------
     */
    public function getCsrfToken(){
        if($this->_csrfToken===null)
        {
            $session = Yii::app()->session;
            $csrfToken=$session->itemAt($this->csrfTokenName);

            if($csrfToken===null)
            {
                $csrfToken = sha1(uniqid(mt_rand(),true));
                $session->add($this->csrfTokenName, $csrfToken);
            }
            $this->_csrfToken = $csrfToken;
        }

        return $this->_csrfToken;
    }

    //將使用session驗證
    public function validateCsrfToken($event)
    {

        if($this->getIsPostRequest())
        {
            // only validate POST requests
            $session=Yii::app()->session;
            if($session->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName]))
            {
                $tokenFromSession=$session->itemAt($this->csrfTokenName);
                $tokenFromPost=$_POST[$this->csrfTokenName];
                $valid=$tokenFromSession===$tokenFromPost;
            }
            else
            $valid=false;
            if(!$valid)
                throw new CHttpException(400,Yii::t('yii','The CSRF token could not be verified.'));
        }
    }
    //重寫httprequest中的方法
    protected function normalizeRequest()
    {
        parent::normalizeRequest();

        //remove the event handler CSRF if this is a route we want skipped
        if($this->enableCsrfValidation)
        {
            $url=Yii::app()->getUrlManager()->parseUrl($this);
            foreach($this->noCsrfValidationRoutes as $route)
            {

                if(strpos($url,$route)===0)

                $result = Yii::app()->detachEventHandler('onBeginRequest',array($this,'validateCsrfToken'));
            }
        }
    }


}
在配置文件中加:

'request'=>array(
			'class' => 'cfg_common.components.HttpRequest',
            'enableCsrfValidation'=>true,
            'enableCookieValidation'=>true,
            'noCsrfValidationRoutes'=>array(//不需要CSEF驗證的URL
				'goods/cart',
				'goods/getOrder',
				'orders/notifyUrl',
				'orders/returnUrl',
				'orders/notifyUrlWap',
				'orders/returnUrlWap',
				'index/saveOrder',
			),
        ),
最後搞定


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章