1 Star 0 Fork 8

桃子/WAFPHP

forked from /WAFPHP 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
WAFPHP.php 13.66 KB
一键复制 编辑 原始数据 按行查看 历史
Zoa 提交于 2015-09-16 21:58 +08:00 . 「修改」精简无用方法
<?php
/**
* User: Zoa Chou
* Date: 15/7/30
*/
namespace WAFPHP;
use WAFPHP\Common\Common;
use WAFPHP\Lib\Model\ModelException;
// 防护系统前缀,避免与其他原程序定义变量冲突
defined('WAF_PREFIX') or define('WAF_PREFIX','WAF_');
// 当前系统所在文件路径
defined('WAF_ROOT') or define('WAF_ROOT',__DIR__.DIRECTORY_SEPARATOR);
// 当前系统配置文件
defined(WAF_PREFIX.'CONFIG') or define(WAF_PREFIX.'CONFIG','config.default');
// 当前系统开始执行时间
defined(WAF_PREFIX.'NOW') or define(WAF_PREFIX.'NOW',microtime(true));
// 当前系统开始执行内存占用大小
defined(WAF_PREFIX.'RAM') or define(WAF_PREFIX.'RAM',memory_get_usage());
class WAFPHP{
/* 系统运行所需数据定义 */
const WAF_VERSION = '0.1';// 版本信息
const WAF_EXT = '.class.php';// 类文件后缀
const SESSION_NAME = 'WAFPHP_SESSION_ID';// 系统session ID名称
const SESSION_LIFETIME = 600;// 系统session的存活时间,存活时间内访问将会刷新存活时间,此时间应长于白名单存活时间
const MODEL_CLASS = __NAMESPACE__.'\\Lib\\Model\\';// Model 模块命名空间
const WAF_CLASS = __NAMESPACE__.'\\Lib\\Waf\\';// Waf 模块命名空间
const CONF_PATH = WAF_ROOT.'Conf'.DIRECTORY_SEPARATOR;
const RUNTIME_PATH = WAF_ROOT.'Runtime'.DIRECTORY_SEPARATOR;// Runtime目录
static private $instance = null;// 当前系统静态示例
static protected $init = null;// 资源初始化标识,当资源初始化后系统运行结束将自动释放所占资源
static protected $quit = null;// 系统退出标识
public $Model = null;// Model object,供子模块调用
public $Log = null;// Log object,供子模块调用
private $config = null;// 系统运行配置
private $resultMsg = null;// 结果的详细信息
private $registerShutdown = null;// register_shutdown_function的callback钩子,用于系统退出后及时清除callback钩子
// Model 模式定义,用于选择使用哪种模式保存访问统计
const MODEL_TYPE = array(
'FILE' => 1,// 文件模式保存
'MYSQL' => 2,// mysql模式保存
'MEMCACHE' => 3,// memcache模式保存
'REDIS' => 4,// redis模式保存
);
/* 系统运行所需数据定义 */
/* 客户端数据定义 */
protected $client = null;// 客户端请求信息
/* 客户端数据定义 */
/*
* 系统初始化
*/
private function __construct($config=''){
// 确保即使异常退出也能执行quit方法
$this->registerShutdown = new UnRegisterCallback(array($this, "quit"));
register_shutdown_function(array($this->registerShutdown, "register"));
// 自动加载类
spl_autoload_register(array($this,'autoLoad'));
// 获取当前客户端请求信息
$this->client = self::getCurrentClient();
// 设置初始化标识
self::$init = true;
// 装载系统运行配置,并根据配置执行检测
$this->setup($config);
}
/*
* 兼容5.3.3以下版本PHP
*/
private function WAFPHP(){
$this->__construct();
}
/*
* 单例模式,防止被克隆
*/
private function __clone(){
die('WAFPHP can\'t be cloned');
}
/*
* 系统实例化
*/
public static function getInstance($config=''){
if(!self::$instance instanceof self){
self::$instance = new self($config);
}
return self::$instance;
}
/*
* 自动加载类方法
*/
private function autoLoad($class){
$classArr = explode('\\',$class);
// 如果根命名空间与当前相同则去除根命名空间目录
if($classArr[0] == __NAMESPACE__){
unset($classArr[0]);
}
// 构造适合当前系统的类库绝对路径路径
$classStr = implode(DIRECTORY_SEPARATOR,$classArr);
require_once WAF_ROOT.$classStr.self::WAF_EXT;
}
/*
* 装载系统运行配置
*/
private function setup($config=''){
// 生成Runtime目录
if(!is_dir(self::RUNTIME_PATH) && !mkdir(self::RUNTIME_PATH,0755)){
die('Failed to create runtime folders in '.self::RUNTIME_PATH);
}
// 如果传递config则把该config作为本次系统运行配置
if(!$config || !is_array($config)){
$this->config = self::getCurrentConfig();
}else{
$this->config = $config;
}
// 以系统配置启用日志
$this->Log = $this->setupLog(Common::getConfig('debug_level',$this->config));
// 以系统配置启用Model
$this->Model = $this->setupModel($this->config);
}
/*
* 获取系统配置指定的指定model实例
*/
private function setupModel($config=''){
// 根据配置实例化Model对应模块
$modelStartTime = Common::click();
$modelStartRAM = Common::RAMClick();
$modelClass = self::MODEL_CLASS.'Model';
try{
$Model = call_user_func(
array($modelClass,'getInstance'),
Common::getConfig('model_type',$config),
Common::getConfig('model_config',$config)
);
}catch (ModelException $e){
$this->Log->error(__METHOD__,'Model throw exception '.$e->getMessage());
throw new WAFPHPException($e->getMessage());
}
// 系统开启时获取有效session
if(Common::getConfig('waf_on',$this->config)){
$this->client['session'] = $Model->getSession($this->client);
}
$modelEndTime = Common::click();
$modelEndRAM = Common::RAMClick();
// 开始记录系统运行信息
$this->Log->debug(__METHOD__,
'WAFPHP start at '.date('Y-m-d H:i:s',Common::getDefine('now')).
',session '.$this->client['session']
);
$this->Log->debug(__METHOD__,sprintf('Model loading use time %fs,RAM %s',($modelEndTime-$modelStartTime),Common::convertUnit($modelEndRAM-$modelStartRAM)));
return $Model;
}
private static function setupLog($debugLevel){
$Log = Lib\Log\Log::getInstance($debugLevel);
return $Log;
}
/*
* 开始执行检测
*/
public function runCheck(){
$checkResult = $this->run();
$this->quit($checkResult);
return $checkResult;
}
/*
* 获取检测结果详细信息
*/
public function getResultMsg(){
return $this->resultMsg;
}
/*
* 检测当前客户端请求是否合法
*/
private function run(){
// 关闭脚本检测则直接返回
if(!Common::getConfig('waf_on',$this->config)){
return true;
}
// 黑名单检测,中靶直接返回结果
if($this->blackCheck()){
return false;
}
// 白名单检测,中靶直接返回结果
if($this->whiteCheck()){
return true;
}
// 脚本检测
$wafStartTime = Common::click();
$wafStartRAM = Common::RAMClick();
$wafClass = self::WAF_CLASS.'Waf';
$Waf = new $wafClass();
// 添加开启的检测脚本进待执行队列
foreach(Common::getConfig('script_list',$this->config) as $key => $value) {
// 排除未开启的检测脚本
if(!$value){
continue;
}
$scriptName = self::WAF_CLASS.ucfirst(strtolower($key));
$scriptConfig = Common::getConfig('WAF_'.$key.'_CONFIG',$this->config);
$Waf->addScript($scriptName,$scriptConfig);
}
// 执行脚本
$scriptResult = $Waf->run($this->client);
if(!$scriptResult){
$this->resultMsg = $Waf->getError();
}
$wafEndTime = Common::click();
$wafEndRAM = Common::RAMClick();
$this->Log->debug(__METHOD__,sprintf('Script detection running use time %fs,RAM %s',($wafEndTime-$wafStartTime),Common::convertUnit(($wafEndRAM-$wafStartRAM))));
return $scriptResult;
}
/*
* 获取当前系统配置文件配置
*/
public static function getCurrentConfig(){
return require_once self::CONF_PATH.constant(WAF_PREFIX.'CONFIG').'.php';
}
/*
* 获取当前请求客户端信息
*/
private static function getCurrentClient(){
// 获取客户端请求信息
$client['ip'] = Common::getClientIp();// 客户端IP
$client['get'] = $_GET;// 客户端GET请求数据
$client['post'] = $_POST;// 客户端POST数据
$client['cookie'] = $_COOKIE;// 客户端COOKIE数据
$client['server'] = $_SERVER["HTTP_HOST"];// 所请求host
$client['ua'] = $_SERVER['HTTP_USER_AGENT'];// 客户端UA
$client['uriHash'] = md5($client['server'].$_SERVER['SCRIPT_NAME']);// 请求uri的MD5校验
return $client;
}
/*
* 检查当前客户端是否为黑名单
*/
public function blackCheck($client = ''){
$client = $client ? $client : $this->client;
// 先检查全局黑名单设置
$blackIP = Common::getConfig('black_ip',$this->config);
$blackUA = Common::getConfig('black_ua',$this->config);
// IP黑名单
if(Common::checkIP($client['ip'],$blackIP)){
$this->resultMsg = 'Black IP list';
$this->Log->info(__METHOD__,'The client ip['.$client['ip'].'] was in black IP list');
return true;
}
// UA黑名单
if(Common::checkUA($client['ua'],$blackUA,
Common::getConfig('black_ua_ignore_case',$this->config)
)){
$this->resultMsg = 'Black UA list';
$this->Log->info(__METHOD__,'The client ua['.$client['ua'].'] was in black ua list');
return true;
}
// 实时黑名单
if($this->Model->isBlack($client)){
$this->resultMsg = 'Client in temporary black list';
$this->Log->info(__METHOD__,'The client ip['.$client['ip'].'] was in temporary black list');
return true;
}else{
return false;
}
}
/*
* 检查当前客户端是否为白名单
*/
public function whiteCheck($client = ''){
$client = $client ? $client : $this->client;
// 先检查全局白名单设置
$whiteIP = Common::getConfig('white_ip',$this->config);
$whiteUA = Common::getConfig('white_ua',$this->config);
// IP白名单
if(Common::checkIP($client['ip'],$whiteIP)){
$this->resultMsg = 'White IP list';
$this->Log->info(__METHOD__,'The client ip['.$client['ip'].'] was in white IP list');
return true;
}
// UA白名单
if(Common::checkUA($client['ua'],$whiteUA,
Common::getConfig('white_ua_ignore_case',$this->config),
Common::getConfig('white_ua_dns_reverse',$this->config),
$client['ip']
)){
$this->resultMsg = 'White UA list';
$this->Log->info(__METHOD__,'The client ua['.$client['ua'].'] was in white ua list');
return true;
}
// 实时白名单
if($this->Model->isWhite($client)){
$this->resultMsg = 'Client in temporary white list';
$this->Log->info(__METHOD__,'The client session['.$client['session'].'] was in temporary white list');
return true;
}else{
return false;
}
}
/*
* 添加黑名单
*/
public function addBlackList($ip=''){
$ip = $ip ? $ip : $this->client['ip'];
return $this->Model->addBlackList($ip,Common::getConfig('black_list_lifetime',$this->config));
}
/*
* 添加白名单
*/
public function addWhiteList($session='',$ip=''){
$ip = $ip ? $ip : $this->client['ip'];
$session = $session ? $session : $this->client['session'];
return $this->Model->addWhiteList($session,$ip,Common::getConfig('white_list_lifetime',$this->config));
}
/*
* 清理系统所占资源,退出系统
*/
public function quit($checkResult=false){
$this->Log->debug(__METHOD__,sprintf('system running use time %fs,RAM %s',Common::click(),Common::convertUnit(Common::RAMClick())));
$resultMsg = $this->resultMsg;
if(self::$init !== null && self::$quit === null){
self::$quit = true;
spl_autoload_unregister(array($this,'autoLoad'));
// 开启debug时将系统debug信息写入log
if(Common::getConfig('debug_level',$this->config)){
$this->Log->writeLog();
}
// 清理Model所占资源
if(is_object($this->Model)){
$this->Model->quit();
}
// 注销register_shutdown_function,避免影响其他程序
$this->registerShutdown->unRegister();
}
}
}
class WAFPHPException extends \Exception{}
/*
* 注销callback类型的系统调用类,规避PHP无法注销callback问题
*/
class UnRegisterCallback{
private $callback;// 储存的callback
/*
* 储存callback
*/
public function __construct($callback){
if(is_callable($callback)) {
$this->callback = $callback;
}
else {
throw new WAFPHPException("Not a Callback");
}
}
/*
* callback钩子,当钩子被注销后callback失效
*/
public function register(){
if($this->callback == false){
return false;
}
// 调用callback
$callback = $this->callback;
$callback();
return true;
}
/*
* 注销callback钩子
*/
public function unRegister(){
$this->callback = false;
return true;
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/taoyy/WAFPHP.git
[email protected]:taoyy/WAFPHP.git
taoyy
WAFPHP
WAFPHP
master

搜索帮助