解决跨域、https、RawBody获取数据、Csrf等问题 [ 1.1 版本 ]
<?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);
}
zh761324952
注册时间:2014-05-26
最后登录:2023-04-07
在线时长:10小时45分
最后登录:2023-04-07
在线时长:10小时45分
- 粉丝4
- 金钱280
- 威望50
- 积分880
热门源码
- 基于 Yii 2 + Bootstrap 3 搭建一套后台管理系统 CMF
- 整合完 yii2-rbac+yii2-admin+adminlte 等库的基础开发后台源码
- 适合初学者学习的一款通用的管理后台
- yii-goaop - 将 goaop 集成到 Yii,在 Yii 中优雅的面向切面编程
- yii-log-target - 监控系统异常且多渠道发送异常信息通知
- 店滴云1.3.0
- 面向对象的一小步:添加 ActiveRecord 的 Scope 功能
- Yii2 开源商城 FecShop
- 基于 Yii2 开发的多店铺商城系统,免费开源 + 适合二开
- leadshop - 基于 Yii2 开发的一款免费开源且支持商业使用的商城管理系统
共 1 条评论
/** * 初始化 * (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; }