zh761324952 2016-12-30 18:05:34 8289次浏览 1条评论 12 1 0
<?php
class HttpRequest extends CHttpRequest
{
    /**
     * 能否 跨域
     * @var boolean | array
     */
    public $enableCrossValidation = true;
    /**
     * 跨域 域名
     * @var string | array
     */
    public $crossDomainName = '*';
    /**
     * 是否强制 https
     * @var boolean | array
     */
    public $enableHttpsValidation = true;
    /**
     * 是否RawBody获取数据
     * @var boolean | array
     */
    public $enableRawBodyValidation = true;
    
    /**
     * 删除 CsrfToken 使其更新
     * @return boolean
     */
    public function unsetCsrfToken()
    {
        $cookie = $this->getCookies();
        if(isset($cookie[$this->csrfTokenName]->value)) {
            unset($cookie[$this->csrfTokenName]);
        }
        return true;
    }
    
    /**
     * (non-PHPdoc)
     * @see CHttpRequest::normalizeRequest()
     */
    protected function normalizeRequest()
    {
        header('X-Author: ChangHai Zhan');
        header('X-Version: ' . Helper::getIpadVersion());
        header('X-Powered-By: ChangHai Zhan');
        $old = $this->enableCsrfValidation;
        $this->enableCsrfValidation = false;
        parent::normalizeRequest();
       $this->enableCsrfValidation = $old;
    }
    
    /**
     * (non-PHPdoc)
     * @see CHttpRequest::validateCsrfToken()
     */
    public function validateCsrfToken($event)
    {
        if ($this->enableCsrfValidation && isset($event->enableCsrfValidation)) {
            $this->enableCsrfValidation = $this->validate($event, $event->enableCsrfValidation);
        }
        if ($this->enableCsrfValidation) {
            if ($this->getIsPostRequest() ||
                $this->getIsPutRequest() ||
                $this->getIsPatchRequest() ||
                $this->getIsDeleteRequest())
            {
                $cookies=$this->getCookies();
                $method=$this->getRequestType();
                switch($method)
                {
                    case 'POST':
                        $userToken=$this->getPost($this->csrfTokenName);
                        break;
                    case 'PUT':
                        $userToken=$this->getPut($this->csrfTokenName);
                        break;
                    case 'PATCH':
                        $userToken=$this->getPatch($this->csrfTokenName);
                        break;
                    case 'DELETE':
                        $userToken=$this->getDelete($this->csrfTokenName);
                }
                if (!empty($userToken) && $cookies->contains($this->csrfTokenName))
                {
                    $cookieToken=$cookies->itemAt($this->csrfTokenName)->value;
                    $valid=$cookieToken===$userToken;
                }
                else
                    $valid = false;
                if (!$valid) {
                    if (isset($event->enableCsrfException)) {
                        $this->evaluateExpression($event->enableCsrfException, array($event, $this));
                    } else {
                        throw new CHttpException(400, Yii::t('yii','The CSRF token could not be verified.'));
                    }
                }
            }
            if (isset($_POST[$this->csrfTokenName])) {
                unset($_POST[$this->csrfTokenName]);
            }
        }
    }
    
    /**
     * 跨域程序
     */
    public function validateCrossDomain($event)
    {
        if ($this->enableCrossValidation && isset($event->enableCrossValidation)) {
            $this->enableCrossValidation = $this->validate($event, $event->enableCrossValidation);
            $this->crossDomainName = $event->crossDomainName;
        }
        if ($this->enableCrossValidation && isset($_SERVER['HTTP_ORIGIN'])) {
            if ($this->crossDomainName == '*') {
                $this->headerCrossDomain($_SERVER['HTTP_ORIGIN']);
            } elseif (is_array($this->crossDomainName) && in_array($_SERVER['HTTP_ORIGIN'], $this->crossDomainName)) {
                $this->headerCrossDomain($_SERVER['HTTP_ORIGIN']);
            } elseif ( !is_array($this->crossDomainName) && $this->crossDomainName) {
                $this->headerCrossDomain($this->crossDomainName);
            }
        }
    }
    
    /**
     * 跨域程序
     * @param string $domain
     */
    public function headerCrossDomain($domain = '')
    {
        if ($domain == '') {
            $domain = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
        }
        if ($domain != '') {
            header('Access-Control-Allow-Credentials: true');
            header('Access-Control-Allow-Origin: ' . $domain);
        }
    }
    
    /**
     * 例外的
     * @param unknown $event
     * @param unknown $validation array(false, 'actionName', 'actionName' => false) 
     * @return boolean
     */
    public function validate($event , $validation)
    {
        if (is_array($validation) && in_array($event->getAction()->id, $validation)) {
            return true;
        } elseif (is_array($validation) && isset($validation[$event->getAction()->id])) {
            return !!$validation[$event->getAction()->id];
        } elseif (is_array($validation)) {
            return isset($validation[0]) && ($validation[0] === true || $validation[0] === false) ? $validation[0] : true;
        } else {
            return $validation === true ? true : false;
        }
    }
    
    /**
     * 是否强制使用 https
     * @param unknown $event
     */
    public function validateHttpsMust($event)
    {
        if ($this->enableHttpsValidation && isset($event->enableHttpsValidation)) {
            $this->enableHttpsValidation = $this->validate($event, $event->enableHttpsValidation);
        }
        if ($this->enableHttpsValidation && !$this->getIsSecureConnection()) {
            $url = $this->getUrl();
            if (strpos($url, '/') === 0 && strpos($url, '//') !== 0) {
                $url = $this->getHostInfo() . $url;
            }
            if (strpos($url, 'https') !== 0) {
                $url = 'https' . ltrim($url, 'http');
                $event->redirect($url);
            }
        }
    }
    
    /**
     * 是否开启 rawBody
     * @param unknown $event
     */
    public function validateRawBody($event)
    {
        if ($this->enableRawBodyValidation && isset($event->enableRawBodyValidation)) {
            $this->enableRawBodyValidation = $this->validate($event, $event->enableRawBodyValidation);
        }
        if ($this->enableRawBodyValidation && $this->getIsPostRequest() && $_POST === array()) {
            $_POST = json_decode($this->getRawBody(), true);
            if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
                $_POST = $this->stripSlashes($_POST);
            }
        }
    }
}

这文件名 HttpRequest.php 放在 path/protected/extensions/rewrites 下
在配置文件中 main 加入代码

    // 自动加载
    'import' => array(
        //……
        'ext.rewrites.*',
    ),

在Controller.php中加入
代码

    /**
     * 过滤IP
     * @var array
     */
    public $ipFilters = array('127.0.0.1', '*');
    /**
     * csrf 攻击
     * @var boolean
     */
    public $enableCsrfValidation = true;
    /**
     * csrf 回调函数
     * @var function
     */
    public $enableCsrfException;
    /**
     * 能否 跨域
     * @var boolean
     */
    public $enableCrossValidation = true;
    /**
     * 跨域 域名
     * @var string
     */
    public $crossDomainName = '*';
    /**
     * 是否强制 https
     * @var boolean
     */
    public $enableHttpsValidation = false;
    /**
     * 是否RawBody获取数据
     * @var boolean | array
     */
    public $enableRawBodyValidation = false;

    /**
     * 初始化
     * (non-PHPdoc)
     * @see CController::init()
     */
    public function init()
    {
        parent::init();
        $this->enableCsrfException = function ($this, $request) {
            throw new CHttpException(200, Yii::t('yii','The CSRF token could not be verified.'), 400);
        };
    }

    /**
     * 进入控制器之前
     * @see CController::beforeAction()
     */
    public function beforeAction($action)
    {
       if (parent::beforeAction($action))
       {
           $this->validateRequest();
           return true;
       }
       else
           return false;
    }

    /**
     * 验证请求的
     * @throws CHttpException
     */
    public function validateRequest()
    {
        if ( !Helper::allowIp(Yii::app()->request->userHostAddress, $this->ipFilters) && $this->route != ltrim(Yii::app()->getErrorHandler()->errorAction, '/'))
            throw new CHttpException(403, '没有权限访问系统');
        Yii::app()->getRequest()->validateHttpsMust($this);
        Yii::app()->getRequest()->validateCrossDomain($this);
        Yii::app()->getRequest()->validateRawBody($this);
        Yii::app()->getRequest()->validateCsrfToken($this);
    }
觉得很赞
  • 评论于 2017-01-03 14:10 举报
        /**
         * 初始化
         * (non-PHPdoc)
         * @see CController::init()
         */
        public function init()
        {
            parent::init();
            $_this = $this;
            $this->enableCsrfException = function ($_this, $request) {
                throw new CHttpException(200, Yii::t('yii','The CSRF token could not be verified.'), 400);
            };
        }
    
    
        /**
         * 过滤ip地址
         * @param unknown $ip
         * @return boolean
         */
        public static function allowIp($ip, $ipFilters)
        {
            if(empty($ipFilters)) {
                return true;
            }
            foreach($ipFilters as $filter) {
                if($filter==='*' || $filter===$ip || (($pos=strpos($filter,'*'))!==false && !strncmp($ip,$filter,$pos))) {
                    return true;
                }
            }
            return false;
        }
    
您需要登录后才可以评论。登录 | 立即注册