基于$_session变量的验证码用于ddos攻击的防御(php实现)

6 篇文章 1 订阅


一、基础知识

1.strpos() 函数

①用法:
strpos() 函数查找字符串在另一字符串中第一次出现的位置,对大小写敏感,且是二进制安全的。
②参数:
strpos(string,find,start)
string 必需。规定要搜索的字符串。
find 必需。规定要查找的字符串。
start 可选。规定在何处开始搜索。
③返回值:
返回字符串在另一字符串中第一次出现的位置(开头位置),如果没有找到字符串则返回 FALSE。(字符串位置从 0 开始,不是从 1 开始。)
④相关函数:

stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)

2.strpos() 函数

①用法:
ltrim() 函数移除字符串左侧的空白字符或其他预定义字符。
②参数:
ltrim(string,charlist)
string 必需。规定要检查的字符串。
charlist 可选。规定从字符串中删除哪些字符。如果省略该参数,则移除下列所有字符: “\0” - NULL ; “\t” - 制表符; “\n” - 换行; “\x0B” - 垂直制表符; “\r” - 回车;" " - 空格
③返回值:
返回已修改的字符串。
④相关函数:

rtrim() - 移除字符串右侧的空白字符或其他预定义字符
trim() - 移除字符串两侧的空白字符或其他预定义字符

3.$_SESSION

①$_SESSION
用于存储关于用户会话(session)的信息,或者更改用户会话的设置,其存储单一用户的信息,并且对于应用程序中的所有页面都是可用的。
您在计算机上操作某个应用程序时,打开它、做些更改、然后关闭它,这很像一次对话(Session)。计算机知道您是谁,它清楚您在何时打开和关闭应用程序。然而,由于 HTTP 地址无法保持状态,Web 服务器并不知道您是谁以及您做了什么。
PHP session 解决了这个问题,它在服务器上存储用户信息(比如用户名称、购买商品等),以便随后使用。然而,会话信息是临时的,在用户离开网站后将被删除。如果您需要永久存储信息,可以把数据存储在数据库中。
Session 的工作机制是:为每个访客创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,或者通过 URL 进行传导。
详解:https://blog.csdn.net/maomaoyu3211/article/details/84241425
②session_start() 函数
session_start() 函数的作用是向服务器注册用户的会话,同时会为用户会话分配一个 UID。因此session_start() 函数必须位于 < html> 标签之前,以便把用户信息存储到 PHP session 中:

<?php session_start(); ?>
 
<html>
<body>
 
</body>
</html>

③存储 Session 变量
存储和取回 session 变量需要使用 PHP 的超级全局变量$_SESSION ,在下面的实例中,我们创建了一个简单的 page-view 计数器。

<?php
//开启会话
session_start();
//isset() 函数检测是否已设置 "views" 变量。
//如果已设置 "views" 变量,我们累加计数器。
//如果 "views" 不存在,则创建 "views" 变量,并把它设置为 1:
if(isset($_SESSION['views']))
{
    $_SESSION['views']=$_SESSION['views']+1;
}else{
    $_SESSION['views']=1;
}
//输出页面浏览量
echo "浏览量:". $_SESSION['views'];
?>

<html>
<body>
 
</body>
</html>

④销毁 Session
如果希望删除某些 session 数据,可以使用 unset() 或 session_destroy() 函数。
unset() 函数用于释放指定的 session 变量:

<?php
session_start();
if(isset($_SESSION['views']))
{
    unset($_SESSION['views']);
}
?>

session_destroy() 将重置 session,您将失去所有已存储的 session 数据。调用 session_destroy() 函数彻底销毁 session:

<?php
session_destroy();
?>

4.fopen() 函数

①用法:
fopen() 函数打开一个文件或 URL。
②参数:
fopen(filename,mode,include_path,context)
filename 必需。规定要打开的文件或 URL。
mode 必需。规定您请求到该文件/流的访问类型。可能的值:

"r" (只读方式打开,将文件指针指向文件头)
"r+" (读写方式打开,将文件指针指向文件头)
"w" (写入方式打开,清除文件内容,如果文件不存在则尝试创建之)
"w+" (读写方式打开,清除文件内容,如果文件不存在则尝试创建之)
"a" (写入方式打开,将文件指针指向文件末尾进行写入,如果文件不存在则尝试创建之)
"a+" (读写方式打开,通过将文件指针指向文件末尾进行写入来保存文件内容)
"x" (创建一个新的文件并以写入方式打开,如果文件已存在则返回 FALSE 和一个错误)
"x+" (创建一个新的文件并以读写方式打开,如果文件已存在则返回 FALSE 和一个错误)

include_path 可选。如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 ‘1’。
context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。

③返回值:
如果 fopen() 失败,它将返回 FALSE 并附带错误信息。可以通过在函数名前面添加一个 ‘@’ 来隐藏错误输出。

5.file_exists() 函数

①用法:
file_exists() 函数检查文件或目录是否存在。
②参数:
file_exists(path)
path 必需。规定要检查的路径。
③返回值:
如果指定的文件或目录存在则返回 true,否则返回 false。

<?php
echo file_exists("test.txt");
?>

//输出:1

6.fputs() 函数

①用法:
fputs() 函数写入文件(可安全用于二进制文件),是 fwrite() 函数的别名。
②参数:
fputs(file,string,length)
file 必需。规定要写入的打开文件。
string 必需。规定要写入文件的字符串。
length 可选。规定要写入的最大字节数。
把 string 的内容写入文件指针 file 处。 如果指定了 length,当写入了 length 个字节或者写完了 string 以后,写入就会停止,视乎先碰到哪种情况。
③返回值:
返回写入的字符数,出现错误时则返回 false。

<?php
$file = fopen("test.txt","w");
echo fputs($file,"Hello World. Testing!");
fclose($file);
?>

//输出:21

7.$_SERVER

$_SERVER 是 PHP 预定义变量之一,可以直接使用,它是一个包含了诸如头信息(header)、路径(path)及脚本位置(script locations)信息的数组。
$_SERVER 数组中的元素由 Web 服务器创建,但不能保证每个服务器都提供全部元素,有的服务器可能会忽略一些,或者提供一些没有在这里列举出来的元素。
$_SERVER数组部分元素如下所示。

$_SERVER['PHP_SELF'] 	当前执行脚本的文件名,与 document root 有关。例如,在地址为 http://c.biancheng.net/test.php/foo.bar 的脚本中使用 $_SERVER['PHP_SELF'] 将得到 /test.php/foo.bar
$_SERVER['SERVER_ADDR'] 	当前运行脚本所在服务器的 IP 地址
$_SERVER['SERVER_NAME'] 	当前运行脚本所在服务器的主机名。如果脚本运行于虚拟主机中,该名称就由那个虚拟主机所设置的值决定
$_SERVER['SERVER_PROTOCOL'] 	请求页面时通信协议的名称和版本。例如,“HTTP/1.0$_SERVER['REQUEST_METHOD'] 	访问页面使用的请求方法。例如“GET”“HEAD”“POST”“PUT$_SERVER['DOCUMENT_ROOT'] 	当前运行脚本所在的文档根目录。在服务器配置文件中定义
$_SERVER['HTTP_ACCEPT_LANGUAGE'] 	当前请求头中 Accept-Language: 项的内容(如果存在)。例如,“en”
$_SERVER['REMOVE_ADDR'] 	浏览当前页面的用户 IP 地址,注意与 $_SERVER['SERVER_ADDR'] 的区别
$_SERVER['SCRIPT_FILENAME'] 	当前执行脚本的绝对路径
$_SERVER['SCRIPT_NAME'] 	包含当前脚本的路径
$_SERVER['REQUEST_URI'] 	URI 用来指定要访问的页面。例如,“index.html”
$_SERVER['PATH_INFO'] 	包含由客户端提供的、跟在真实脚本名称之后并且在查询语句(query string)之前的路径信息(如果存在)。例如,当前脚本是通过 URL http://c.biancheng.net/php/path_info.php/some/stuff?foo=bar 被访问的,那么 $_SERVER['PATH_INFO'] 将包含 /some/stuff

在浏览器打印出 $_SERVER 数组的代码如下:

<?php
print_r($_SERVER);
?>

浏览器的输出结果如下:

Array
(
    [HTTP_HOST] => localhost
    [HTTP_CONNECTION] => keep-alive
    [HTTP_CACHE_CONTROL] => max-age=0
    [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9, image/webp,*/*;q=0.8
    [HTTP_UPGRADE_INSECURE_REQUESTS] => 1
    [HTTP_USER_AGENT] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36
    [HTTP_ACCEPT_ENCODING] => gzip, deflate, sdch
    [HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.8
    [HTTP_COOKIE] => PHPSESSID=e1bbc84e23bf85691e7c5a4ab07ee0de; pgv_pvi=4369311744; pgv_si=s1775918080; CNZZDATA155540=cnzz_eid%3D1811041545- 1463297631-%26ntime%3D1463303031
    [PATH] => /usr/bin:/bin:/usr/sbin:/sbin
    [SERVER_SIGNATURE] =>
    [SERVER_SOFTWARE] => Apache/2.4.16 (Unix) PHP/7.0.5
    [SERVER_NAME] => localhost
    [SERVER_ADDR] => ::1
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => ::1
    [DOCUMENT_ROOT] => /Library/WebServer/Documents
    [REQUEST_SCHEME] => http
    [CONTEXT_PREFIX] =>
    [CONTEXT_DOCUMENT_ROOT] => /Library/WebServer/Documents
    [SERVER_ADMIN] => you@example.com
    [SCRIPT_FILENAME] => /Library/WebServer/Documents/book/str.php
    [REMOTE_PORT] => 59377
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => GET
    [QUERY_STRING] =>
    [REQUEST_URI] => /book/str.php
    [SCRIPT_NAME] => /book/str.php
    [PHP_SELF] => /book/str.php
    [REQUEST_TIME_FLOAT] => 1463828978.149
    [REQUEST_TIME] => 1463828978
    [argv] => Array
    (
    )
    [argc] => 0
)

8.header() 函数

①用法:
header() 函数向客户端发送原始的 HTTP 报头,因此必须在任何实际的输出被发送之前调用 header() 函数
②参数:
header(string,replace,http_response_code)
string 必需。规定要发送的报头字符串。
replace 可选。指示该报头是否替换之前的报头,或添加第二个报头。默认是 true(替换),false(允许相同类型的多个报头)。
http_response_code 可选。把 HTTP 响应代码强制为指定的值。(PHP 4 以及更高版本可用)

③例如,用户可能会设置一些选项来更改浏览器的默认缓存设置。通过发送上面的报头,您可以覆盖任何这些设置,强制浏览器不进行缓存!

<?php
// Date in the past
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache");
header("Pragma: no-cache");
?>

<html>
<body>

9. exit() 函数

①用法:
exit() 函数输出一条消息,并退出当前脚本,该函数是 die() 函数的别名。
②参数:
exit(message)
message 非必需。规定在退出脚本之前写入的消息或状态号。状态号不会被写入输出。
③返回值:

一般用于报错:

<?php
$site = "http://www.w3cschool.cc/";
fopen($site,"r")
or exit("Unable to connect to $site");
?>

9. imagecreate()函数

①用法:
imagecreate()返回一个表示指定大小的空白图像的图像标识符。
②参数:
resource imagecreate ( int $width , int $height )
width - 图像宽度。height - 图像高度。
③返回值:
成功时返回图像资源标识符,错误时返回FALSE。

二、项目实现

1.工作原理

在每次连接时,系统会临时保存客户端的ip地址并监控其连接频率,如果该连接频率异常,则系统将其视为黑IP地址并以图片的形式发送验证请求。

2.开始界面

此脚本用于前期准备工作以及启动anti_ddos脚本,同时包含一些前端页面的优化:

<?php 
//安全输出函数,若输入参数value为空字符串输出“0”,若value不为空,其中有0把左侧的0都去掉输出value,其中无0输出value
function safe_print($value){
	$value .= "";
	return strlen($value) > 1 && (strpos($value, "0") !== false) ? ltrim($value, "0") : (strlen($value) == 0 ? "0" : $value);
}
//开启会话,记录session
if(!isset($_SESSION)){
	session_start();
}

if(isset($_SESSION['standby'])){

	// 配置
	$_SESSION['standby'] = $_SESSION['standby']+1;

	$ad_ddos_query = 5;// 每秒检测DDOS攻击的请求数
	$ad_check_file = 'check.txt';// 在监测期间把当前状态写入该文件
	$ad_all_file = 'all_ip.txt';// 临时文件
	$ad_black_file = 'black_ip.txt';// 此文件记录僵尸机ip
	$ad_white_file = 'white_ip.txt';// 此文件记录登录访客的ip
	$ad_temp_file = 'ad_temp_file.txt';// 记录登录访客的ip
	$ad_dir = 'anti_ddos/files';// 代表带有脚本的目录
	$ad_num_query = 0;// 从$check_file文件发出的当前每秒请求数​​
	$ad_sec_query = 0;// ​​second from a file $check_file 秒数
	$ad_end_defense = 0;// ​​end while protecting the file $check_file 终结
	$ad_sec = date("s");// 当前秒数
	$ad_date = date("is");// 当前时间
	$ad_defense_time = 100;// ddos​​停止监测的攻击检测时间(秒)
		
	$config_status = "";
	//读写方式打开或创建一个文件,文件指针指向文件末尾进行写入(或读出)。返回创建成功或失败的信息
	function Create_File($the_path){
		$handle = fopen($the_path, 'a+') or die('Cannot create file:  '.$the_path);
		return "Creating ".$the_path." .... done";
	}


	// 在启动检测之前检查所有文件是否存在(不存在新建文件或报错,存在就把文件路径写入$config_status字符串)
	$config_status .= (!file_exists("{$ad_dir}/{$ad_check_file}")) ? Create_File("{$ad_dir}/{$ad_check_file}") : "ERROR: Creating "."{$ad_dir}/{$ad_check_file}<br>";
	$config_status .= (!file_exists("{$ad_dir}/{$ad_temp_file}")) ? Create_File("{$ad_dir}/{$ad_temp_file}") : "ERROR: Creating "."{$ad_dir}/{$ad_temp_file}<br>";
	$config_status .= (!file_exists("{$ad_dir}/{$ad_black_file}")) ? Create_File("{$ad_dir}/{$ad_black_file}") : "ERROR: Creating "."{$ad_dir}/{$ad_black_file}<br>";
	$config_status .= (!file_exists("{$ad_dir}/{$ad_white_file}")) ? Create_File("{$ad_dir}/{$ad_white_file}") : "ERROR: Creating "."{$ad_dir}/{$ad_white_file}<br>";
	$config_status .= (!file_exists("{$ad_dir}/{$ad_all_file}")) ? Create_File("{$ad_dir}/{$ad_all_file}") : "ERROR: Creating "."{$ad_dir}/{$ad_all_file}<br>";

	if(!file_exists ("{$ad_dir}/../anti_ddos.php")){
		$config_status .= "anti_ddos.php does'nt exist!";
	}

	if (!file_exists("{$ad_dir}/{$ad_check_file}") or 
			!file_exists("{$ad_dir}/{$ad_temp_file}") or 
				!file_exists("{$ad_dir}/{$ad_black_file}") or 
					!file_exists("{$ad_dir}/{$ad_white_file}") or 
						!file_exists("{$ad_dir}/{$ad_all_file}") or 
							!file_exists ("{$ad_dir}/../anti_ddos.php")) {

								$config_status .= "Some files does'nt exist!";
								die($config_status);
	}

	// 验证会话是否启动
	require ("{$ad_dir}/{$ad_check_file}");//文件包含check.txt,在监测期间把当前状态写入该文件

	if ($ad_end_defense and $ad_end_defense> $ad_date) {//当前时间在攻击保护时间范围内
		require ("{$ad_dir}/../anti_ddos.php");//文件包含anti_ddos.php
	} else {
		$ad_num_query = ($ad_sec == $ad_sec_query) ? $ad_num_query++ : '1 ';//当前每秒请求数
		$ad_file = fopen ("{$ad_dir}/{$ad_check_file}", "w")//写入方式打开,清除文件内容,如果文件不存在则尝试创建之

		$ad_string = ($ad_num_query >= $ad_ddos_query) ? '<?php $ad_end_defense='.safe_print($ad_date + $ad_defense_time).'; ?>' : '<?php $ad_num_query='. safe_print($ad_num_query) .'; $ad_sec_query='. safe_print($ad_sec) .'; ?>';

		fputs ($ad_file, $ad_string);
		fclose ($ad_file);
	}
}else{

		$_SESSION['standby'] = 1;
		
		$actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";//服务器主机名localhost,REQUEST_URI指定访问的页面(PHP文件) 
		header("refresh:8,".$actual_link);
	?>
		<style type="text/css">
			.loading {display: flex; flex-direction: column; align-items: center; } 
			.loading__msg {font-family: Roboto; font-size: 16px; } 
			.loading__dots {display: flex; flex-direction: row; width: 100%; justify-content: center; margin: 100px 0 30px 0; } 
			.loading__dots__dot {background-color: #44BBA4; width: 20px; height: 20px; border-radius: 50%; margin: 0 5px; color: #587B7F; } 
			.loading__dots__dot:nth-child(1) {animation: bounce 1s 1s infinite; } 
			.loading__dots__dot:nth-child(2) {animation: bounce 1s 1.2s infinite; } 
			.loading__dots__dot:nth-child(3) {animation: bounce 1s 1.4s infinite; } @keyframes bounce {0% {transform: translate(0, 0); } 50% {transform: translate(0, 15px); } 100% {transform: translate(0, 0); } }
		</style>
	<div class="loading" style="margin-top: 11%;">
		<div class="loading__dots">
		<div class="loading__dots__dot"></div>
		<div class="loading__dots__dot"></div>
		<div class="loading__dots__dot"></div>
		</div>
		<div class="loading__msg">
			<center>
				<b style="font-size: 22px;">
					<a target="_blank" style="color: black;">ANTI_DDOS</a> is checking....
				</b>
				<br><br>
			嗨,别担心,这是一个简单的安全验证,
			你只会看到这一次;<br> 您的网页将很快显示!
			 </center></div>
	</div>

<?php exit();

}
?>


3.验证ip脚本

此脚本主要用于获取用户的ip,与黑白名单对比,并增加白名单与黑名单(从临时名单中):


<?php

//返回黑名单或白名单文件中的ip地址,方便后期比较
function getFromfile_source($type){

	$ad_check_file = 'check.txt';// 在监测期间把当前状态写入该文件
	$ad_all_file = 'all_ip.txt';// 临时文件
	$ad_black_file = 'black_ip.txt';// 此文件记录僵尸机ip
	$ad_white_file = 'white_ip.txt';// 此文件记录登录访客的ip
	$ad_temp_file = 'ad_temp_file.txt';// 此文件记录登录访客的ip
	$ad_dir = 'anti_ddos/files';// 代表带有脚本的目录

	//file() 函数把整个文件读入一个数组中,返回值是此数组
	return ($type == "black") ? explode(',', implode(',',file("{$ad_dir}/{$ad_black_file}"))) : ( ($type == "white") ? explode(',', implode(',',file("{$ad_dir}/{$ad_white_file}"))) : explode(',', implode(',',file("{$ad_dir}/{$ad_temp_file}"))) ) ;//explode() 函数把字符串打散为数组。
	//implode() 函数返回由数组元素组合成的字符串
}

$ad_ip = "";
//如果在本地计算机上工作,可以添加以下条件
//and getenv(" HTTP_CLIENT_IP ") != '127.0.0.1' //用户ip
//and getenv(" HTTP_X_FORWARDED_FOR") != '127.0.0.1'


/*
在PHP 中使用 $_SERVER["REMOTE_ADDR"] 来取得客户端的 IP地址,但如果客户端是使用代理服务器来访问,那取到的就
是代理服务器的 IP 地址,而不是真正的客户端 IP 地址。要想透过代理服务器取得客户端的真实 IP 地址,就要使用
$_SERVER["HTTP_X_FORWARDED_FOR"] 来读取。
*/

//获取用户的真实ip地址并用正则检验其是否合法
$ad_ip = (getenv("HTTP_CLIENT_IP") and preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/", getenv(" HTTP_CLIENT_IP "))) ? getenv("HTTP_CLIENT_IP") : ( (getenv("HTTP_X_FORWARDED_FOR") and preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/", getenv(" HTTP_X_FORWARDED_FOR "))) ? getenv("HTTP_X_FORWARDED_FOR") : getenv("REMOTE_ADDR"));

//若此ip地址在黑名单中,退出此php文件
$ad_source = getFromfile_source('black');
if(in_array($ad_ip, $ad_source)) {die();}


$ad_source = getFromfile_source('white');
if(!in_array($ad_ip, $ad_source)) {//如果这个ip不在白名单中

	$ad_source = getFromfile_source('temp'); //获取temp文件中的ip
	if(!in_array($ad_ip, $ad_source)) {//此ip不在temp中
		$_SESSION['nbre_essai']=3; //三次尝试机会
		$ad_file = fopen("{$ad_dir}/{$ad_temp_file}", "a+");
		$ad_string = $ad_ip.',';
		fputs($ad_file, "$ad_string");//将新IP放入temp中(ip第一次访问)
		fclose($ad_file); 
		//???
		$array_for_nom = array('maN','bZ','E','S','i','P','u','1','4','Ds','Er','FtGy','A','d','98','z1sW');
		$nom_form = $array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)]; 
		$_SESSION['variable_du_form'] = str_shuffle($nom_form).$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)];

		include('Verify_your_identity.php');//包含验证身份前端文件,用户的输入界面

		die();
	}elseif(isset($_POST[$_SESSION['variable_du_form']]) AND $_SESSION['nbre_essai']>0){//此ip在temp中且之前试图放入temp中过且仍有机会尝试(第二次访问),通过验证则放入白名单
		$secure = isset($_POST['valCAPTCHA']) ? ($_POST['valCAPTCHA']) : '';//获取用户输入的验证码

		if ($secure == $_SESSION['securecode']){//用户输入(V_y_i)等于系统随机(securitecode),加入白名单中
			$ad_file = fopen("{$ad_dir}/{$ad_white_file}", "a+");
			$ad_string = $ad_ip. ',';
			fputs($ad_file, "$ad_string");
			fclose($ad_file);
			unset($_SESSION['securecode']);
			unset($_SESSION['nbre_essai']);
		}else{//验证,最后一次
			$_SESSION['nbre_essai']--;
			$array_for_nom = array('maN','bZ','E','S','i','P','u','1','4','Ds','Er','FtGy','A','d','98','z1sW');
			$nom_form = $array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)]; 
			$_SESSION['variable_du_form'] = str_shuffle($nom_form).$array_for_nom[rand(0,15)].$array_for_nom[rand(0,15)]; 

			include('Verify_your_identity_LASTCHANCE.php');//包含验证身份文件

			die();
		}
		
	}else {//三次验证码输错加入黑名单
		$ad_file = fopen("{$ad_dir}/{$ad_black_file}", "a+");
		$ad_string = $ad_ip.',';
		fputs($ad_file, "$ad_string");
		fclose($ad_file);
		die();
	}
}
?>

4.提供验证码

此代码在固定序列中随机生成乱码,并将一个图片验证码展现在前端:

<?php
  if(!isset($_SESSION)){
    session_start();
  }
  $largeur  = 120;
  $hauteur  = 40;
  $longueur = 6;
  $liste = '134679ACEFGHIJLMNPRTUVWXY@%$&';//验证码库
  $code    = '';
  $counter = 0;
  //返回一个图像标识符,隐藏报错(此时是空白的)
  $image = @imagecreate($largeur, $hauteur) or die('Impossible d\'initializer GD');
  //在图像上画线防止机器识别(验证码)
  for( $i=0; $i<10; $i++ ){
          imageline($image,// imageline()函数在两个给定点之间绘制一条线段(此处画了两条
          mt_rand(0,$largeur), 
            mt_rand(0,$hauteur),
              mt_rand(0,$largeur), 
                mt_rand(0,$hauteur),
                  imagecolorallocate($image, mt_rand(200,255),
											  mt_rand(200,255),
												mt_rand(200,255)//线段颜色。分别是所需要的颜色的红,绿,蓝成分。这些参数是 0 到 255 的整数
					)
          );
  }

  for( $i=0, $x=0; $i<$longueur; $i++ ) {
    $charactere = substr($liste, rand(0, strlen($liste)-1), 1);
    $x += 10 + mt_rand(0,10);
	//imagechar将字符串的第一个字符画在 image 指定的图像中
    imagechar($image, mt_rand(3,4), $x, mt_rand(4,20), $charactere,
    imagecolorallocate($image, mt_rand(0,155), mt_rand(0,155), mt_rand(0,155)));
    $code .= ($charactere);
  }

  header('Content-Type: image/jpeg');
  imagejpeg($image);
  imagedestroy($image);
  $_SESSION['securecode'] = $code;

?>

三、总结

1.防御效果

此防御策略实现简单,能用于攻击者利用某些僵尸机伪造大量连接请求对服务器发起攻击,此情况下如果某攻击ip三次仍未能通过验证码检测则无法访问网站页面。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.存在问题

此防御策略针对的攻击类型较单一,无法应对多种攻击。此外其效率也有待提高,例如,若有大量随机ip同时对网站发起访问,对每个ip进行验证也会消耗大量资源。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值