除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。
当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。
Session与Cookie:
(1)当第一次访问网站时,Seesion_start()
函数(开启Session,注意该函数前面不能有任何输出)就会创建一个唯一的Session ID,并自动通过HTTP的响应头,将这个Session ID保存到客户端Cookie中(Cookie的名称为PHPSESSID,值为这个Session ID)。同时,也在服务器端创建一个以Session ID命名的文件,用于保存这个用户的会话信息,如下图所示。由于默认生成的这个PHPSESSID cookie的生存期为会话,也就是说关闭浏览器就会过期掉,所以,下次重新浏览时,会重新生成一个session_id。
(2)当同一个用户再次访问这个网站时,也会自动通过HTTP的请求头将Cookie中保存的Seesion ID再携带过来,这时Session_start()函数就不会再去分配一个新的Session ID,而是在服务器的硬盘中去寻找和这个Session ID同名的Session文件,将这之前为这个用户保存的会话信息读出,在当前脚本中应用,达到跟踪这个用户的目的。
(3)PHP中使用Session变量,除了要启动之外,还要经过写入的过程。通过预定义超全局数组 $_SESSION
完成对Session数据的读写。在$_SESSION
关联数组中的键名具有和PHP中普通变量相同的命名规则。注册Session变量的代码如下所示:
<?php
//启动session的初始化
session_start();
//注册session变量,赋值为一个用户的名称
$_SESSION["username"]="skygao";
//注册session变量,赋值为一个用户的ID
$_SESSION["uid"]=1;
?>
(4)执行该脚本后,两个Session变量就会被保存在服务器端的某个文件中,该文件的位置是通过php.ini文件,在session.save_path属性指定的目录下。
(1)编写网站首页。当客户访问首页时,验证请求的Session信息,如果有则显示“欢迎信息”并显示注销按钮(跳转至注销页面),如果没有则要求登录并显示登录按钮(跳转至登录页面)。
(2)编写登录页面。假设已有注册用户DuZZ,密码为123456。登录页面启动Session机制,利用HTML表单收集客户端输入信息,利用PHP语句判断账户密码是否正确,正确则设置Session对象并返回首页,错误则要求继续输入账号密码。
(3)编写注销页面。注销后返回首页。
服务端:本实验基于虚拟机win2008系统的WAMP环境进行,该环境相关配置过程参考文章《【语言环境】WAMP环境部署及优化—以win2008R2SP1为操作系统》。
客户端:浏览器通过IP地址访问所编写网页。
服务端与客户端处于同一个局域网下。
注意若要用到session时,每个页面都需要开启Session,即需要写session_start()
函数。
(1)index.php 首页代码:
<meta charset='utf-8'>
<h1>Session应用案例</h1>
<?php
session_start();//开启session,该函数前不能有任何PHP输出语句
if(isset($_SESSION['userName']) && $_SESSION['userName']=="DuZZ"){
echo "欢迎您,{$_SESSION['userName']} ,请开始测试";
echo "
";
echo "请注销";
}
else{
echo " 请登录";
}
?>
(2)login.php 登录页面代码:
<meta charset="utf-8">
<?php
session_start();//开启session,该函数前不能有任何输出语句
?>
<?php
if(isset($_POST['userSubmit'])){
if(isset($_POST['userName']) && $_POST['userName']=="DuZZ"
&& isset($_POST['userPassword']) && $_POST['userPassword']==123456){
$_SESSION['userName']= $_POST['userName'];
echo "登录成功, 返回首页";
}
else{
echo "用户名或密码错误, 请重新登录";
}
}
else{
$_html=<<<HTML
<h1>用户登录</h1>
<form
action=""
method="post"
>
用户名:<input type="text" name="userName"><br/>
密码:<input type="password" name="userPassword"><br/>
<input type="submit" name="userSubmit" value="登录">
</form>
HTML;
//定界符的结尾一定要顶格写,且后面不能有任何内容
echo $_html;
}
?>
(3)logout.php 注销页面代码:
<meta charset='utf-8'>
<?php
session_start();
session_destroy();//session的注销
echo "注销成功,返回首页";
?>
(1)浏览器访问首页。输入网址http://172.16.1.1/PHP/Session/index.php
。
(3)输入用户名:DuZZ,密码123456。点击登录,提示登录成功,点击返回首页。
(4)登录后的首页显示内容与未登录不一样,因为代码根据是否有Session进行判断并分支执行。
(5)若要退出,则点击注销,进入注销页面。
(6)点击返回首页则是初始的首页界面。
会话劫持(Session hijacking),这是一种通过获取用户Session ID后,使用该Session ID登录目标账号的攻击方法,此时攻击者实际上是使用了目标账户的有效Session。会话劫持的第一步是取得一个合法的会话标识来伪装成合法用户,因此需要保证会话标识不被泄漏。
(1)目标用户需要先登录站点;
(2)登录成功后,该用户会得到站点提供的一个会话标识SessionID;
(3)攻击者通过某种攻击手段捕获Session ID;攻击者获取SessionID的方式有多种:
(4)攻击者通过捕获到的Session ID访问站点即可获得目标用户合法会话。
(1)更改Session名称。PHP中Session的默认名称是PHPSESSID,此变量会保存在Cookie中,如果攻击者不分析站点,就不能猜到Session名称,阻挡部分攻击。
(2)关闭透明化Session ID。透明化Session ID指当浏览器中的Http请求没有使用Cookie来存放Session ID时,Session ID则使用URL来传递。
(3)设置HttpOnly。通过设置Cookie的HttpOnly为true,可以防止客户端脚本访问这个Cookie,从而有效的防止XSS攻击。
(4)关闭所有phpinfo类dump request信息的页面。
(5)验证HTTP头部信息。
(6)加入Token校验。同样是用于检测请求的一致性,给攻击者制造一些麻烦,使攻击者即使获取了Session ID,也无法进行破坏,能够减少对系统造成的损失。但Token需要存放在客户端,如果攻击者有办法获取到Session ID,那么也同样可以获取到Token。
会话固定(Session fixation)是一种诱骗受害者使用攻击者指定的会话标识(SessionID)的攻击手段。这是攻击者获取合法会话标识的最简单的方法。(让合法用户使用黑客预先设置的sessionID进行登录,从而使Web不再进行生成新的sessionID,从而导致黑客设置的sessionId变成了合法桥梁。)
会话固定也可以看成是会话劫持的一种类型,原因是会话固定的攻击的主要目的同样是获得目标用户的合法会话,不过会话固定还可以是强迫受害者使用攻击者设定的一个有效会话,以此来获得用户的敏感信息。
(1)攻击者通过某种手段重置目标用户的SessionID,然后监听用户会话状态;
(2)目标用户携带攻击者设定的Session ID登录站点;
(3)攻击者通过Session ID获得合法会话。
(1)每当用户登陆的时候就进行重置sessionID;
(2)sessionID闲置过久时,进行重置sessionID;
(3)大部分防止会话劫持的方法对会话固定攻击同样有效。如设置HttpOnly,关闭透明化Session ID,User-Agent验证,Token校验等。
(1)了解什么是cookie和session;
(2)初步理解session与cookie的运行机制;
(3)掌握Session机制的应用;
(4)了解Session的攻击方式和防御手段。
(5)结合视频《Cookie、Session、Token究竟区别在哪?如何进行身份认证,保持用户登录状态?》,加深对cookie、Session和token三者的理解。
[1] 《Session攻击(会话劫持+固定)与防御 》后续了解里面代码。
[2] 《session (计算机术语)》
[3] 《【PHP基础】Session基础知识、应用案例代码及攻防》
[3] 《Cookie/Session机制详解》