韩顺平PHP视频听课笔记
第84讲 http请求详解,防盗链技术
1, 通过httpwatch插件来抓取http请求内容
2, http1.0短连接, http1.1长连接
http1.0短连接:每次通信时间很短,效率极低,已被废除。
http1.1长连接:通话时间长。只要现在基本都采用http1.1。
只要Connection的状态为keep-alive,就说明是通话状态
3, http是tcp/ip协议的一个应用层协议,http也是我们web开发的基础。
4, 一个问题:看一个test.html页面
<h1>abc</h1>
<img src=”news.jpg”/>
<img src=”news2.jpg”/>
问浏览器发出几次请求?
A.1次 B.2次 C.3次
答案:3次
第一次:向服务器取出该页面本身
第二次:向服务器取出图片news.jpg。
(向网络取图片是向图片服务器发请求,把大量图片放到一个带宽很足的地方供用户使用,采用了图床技术。服务器读取到img元素,就会到src指定的url去提取图片,如果url不是网络路径,服务器就从src指定的路径获取,实质上对服务器而言网络路径和本地路径是一样的。)
第三次:向服务器取出图片news2.jpg
那么如果把test.html改成如下这样,浏览器会发送几次请求?
<h1>abc</h1>
<img src=”news.jpg”/>
<img src=”news.jpg”/>
答案是两次。浏览器第一次请求过一次news.jpg,第二次再次请求之前,会判断出news.jpg已经请求过一次,就会从本地缓存的图片里提取,而不会再次向服务器发送http请求
例子:
<h1>abc</h1>
<img width="200px" src="Desert.jpg"/>
<img width="200px" src="Koala.jpg"/>
<h1>abc</h1>
<img width="200px" src="Desert.jpg"/>
<img width="200px" src=" Desert.jpg"/>
5.http请求:
客户端连上服务器之后,向服务器请求某个web资源,称之为客户端向服务器发送了一个http请求。一个完整的http请求包括如下内容:一个请求行,若干消息头,以及实体内容,其中的一些消息头和实体内容都是可选的,消息头部和实体内容之间要用空行隔开。如下所示:
(Request-Line) GET /hsp/lesson84http/Desert.jpg HTTP/1.1
请求行,用于描述客户端的请求方式,请求的资源名称,以及使用的http协议版本号。
GET /hsp/lesson84http/Desert.jpg HTTP/1.1 表示发送的是GET请求,请求资源是/hsp/lesson84http/Desert.jpg
Host localhost
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0 【告诉服务器我的浏览器内核,操作系统】
Accept */* 【表示可接受任何数据。jpg/gif就表示只能接受jpg/gif类型的数据。】
Accept-Language zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 【页面语言】
Accept-Encoding gzip, deflate【表示接受什么样的数据压缩格式】
Referer http://localhost/hsp/lesson84http/test.html 【表示我是从哪里来的,我从本机访问其他网站,这个Referer里面就会写入我本机的路径。这个消息头很重要,在防盗链技术中起关键作用。可以根据Referer的值来对指定的地址来源设置查看权限。】
Connection keep-alive 【keep-alive表示不要立即断掉我们的请求】
If-Modified-Since Tue, 14 Jul 2009 05:32:31 GMT
If-None-Match "ce875-46ea3c3ddc7bb"
Cache-Control max-age=0
从User-Agent到Cache-Control max-age=0是多个消息头,用于描述客户端请求那台主机,以及客户端的一些环境信息等。
$_SERVER全局变量中保存了以上所有的消息头的信息。同时还有其他额外的信息。
可以使用以下代码进行打印
<?php
foreach($_SERVER as $key=>$val){
echo "$key = $val<br>";
}
?>
可以得到如下结果:
HTTP_HOST = localhost
HTTP_USER_AGENT = Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101
Firefox/51.0
HTTP_ACCEPT = text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_LANGUAGE = zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
HTTP_ACCEPT_ENCODING = gzip, deflate
HTTP_CONNECTION = keep-alive
HTTP_UPGRADE_INSECURE_REQUESTS = 1
PATH =
C:ProgramDataOracleJavajavapath;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;C:Program
Files (x86)NVIDIA
CorporationPhysXCommon;D:AMPmysqlin;D:AMPapachein;D:AMPphp;D:AMPphpext;
SystemRoot = C:Windows
COMSPEC = C:Windowssystem32cmd.exe
PATHEXT = .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY
WINDIR = C:Windows
SERVER_SIGNATURE =
SERVER_SOFTWARE = Apache/2.4.25 (Win64) OpenSSL/1.0.2j PHP/5.6.29
SERVER_NAME = localhost
SERVER_ADDR = 127.0.0.1
SERVER_PORT = 80
REMOTE_ADDR = 127.0.0.1
DOCUMENT_ROOT = D:/AMP/apache/htdocs
REQUEST_SCHEME = http
CONTEXT_PREFIX =
CONTEXT_DOCUMENT_ROOT = D:/AMP/apache/htdocs
SERVER_ADMIN = admin@example.com
SCRIPT_FILENAME = D:/AMP/apache/htdocs/hsp/lesson84http/test2.php
REMOTE_PORT = 57887
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.1
REQUEST_METHOD = GET
QUERY_STRING =
REQUEST_URI = /hsp/lesson84http/test2.php
SCRIPT_NAME = /hsp/lesson84http/test2.php
PHP_SELF = /hsp/lesson84http/test2.php
REQUEST_TIME_FLOAT = 1489723781.681
REQUEST_TIME = 1489723781
其中有个REMOTE_ADDR记录了来访者的IP可以通过这个变量来对来访者进行IP封禁等操作。封禁用户代码示例:
<?php
If($_SERVER[‘REMOTE_ADDR’]==”192.168.1.102”){
//跳转到一个警告页面
Header(“Location: Err.php“);
}
?>
Err.php:
<?php
Echo “你是一个非法用户!”;
?>
$_SERVER中常用的变量:
HTTP_HOST = localhost
REMOTE_ADDR 可以获取来访者IP
DOCUMENT_ROOT 可以获取服务器的主目录
6.请求方式
请求行中的GET称之为请求方式,请求方式有:POST, GET, HEAD, OPTIONS, TRACE, PUT
常用的有:POST,GET
GET/POST区别有哪些
1, 安全性get请求的数据会显示在地址栏上,post请求的数据,放在http协议的消息体,post请求更加安全
2, 从可以提交的数据大小看:
2.1,http协议本身并没有限制数据大小
2.2,浏览器在对get和post请求做显示,get请求数据2k+35,post请求数据无限制
3, get请求可以更好的添加到收藏夹。浏览器的收藏夹收藏的是一个url,get请求的参数能保存在这个url里。而post请求的参数放在消息体里,所以不便于收藏。
现在我们使用http请求,练习一下防盗链技术:
<?php
$str="
<html>
<a href='http://localhost/hsp/lesson84http/test3.php'>我想访问test3.php</a>
</html>
";
echo $str;
?>
编辑http://localhost/hsp/lesson84http/test3.php
<?php
if(isset($_SERVER['HTTP_REFERER'])){
if(strpos($_SERVER['HTTP_REFERER'], "http://localhost/http/hsp/lesson84http")==0){
echo $_SERVER['HTTP_REFERER'].'<br>';
echo strpos($_SERVER['HTTP_REFERER'], "http://localhost/http/hsp/lesson84http").'<br>';
echo "欢迎你!!";
}else{
echo "就是不让你访问!!";
}
}
?>
代码意图:从一个非当前路径的php文件test5.php里使用超链接访问到当前路径test3.php
在test3.php里设置非当前路径的文件来访问就提示“就是不让你访问”
但是预期效果不对。最后把strpos()后面的”==”修改为”===”就行了。
原因可能是因为strpos()函数的第二个参数为http://localhost/http/hsp/lesson84http,这个字符串在strpos的第一个参数$_SERVER['HTTP_REFERER']中不存在,所以函数返回一个空值
而使用”==”来判断是否相等,可能会认为空值和0相等。如果使用”===”就会避开这个隐患。