web服务器之ApacheCookie 和 session

无状态协议是指协议对事物处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则必须
重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它应答就很
快。
HTTP是超本文传输协议,顾名思义,这个协议支持超文本的传输。什么是超文本?说白了就是使用
HTML编写的页面。通常,我们使用客户端浏览器访问服务器的资源,最常见的URL也是以html为后缀
的文件,因此可以说超文本是网络上最主要的资源。
既然HTTP协议的目的是在于支持超文本的传输,也就是资源的传输,那么客户端浏览器向HTTP服务器
发送请求,继而HTTP服务器将相信资源发回给客户端这样一个过程中,无论对于客户端还是服务器,都
没有必要记录这个过程,因为每一次请求和响应都是相对独立的,一般而言,一个URL对应着一个唯一
的超文本,正是因为这样的唯一性,使得记录用户的行为状态变得毫无意义,所以,HTTP协议被设计为
无状态的连接协议符合它本身的需求。

HTTP协议这种特性有优点也有缺点,优点在于解放了服务器,每一次请求"点到为止",不会造成不必要
的连接占用,缺点在于如果为了保留状态,每次请求都会传输大量的重复信息内容。

可是随着 Web 的不断发展,很多业务都需要对通信状态进行保存.
如果是一次性会话的过程: 打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器
但目前有很多WEB访问场景,并不是一次性会话,而是多次相关的会话,比如:

登录场景:
打开浏览器 -> 浏览到登陆页面 -> 输入用户名和密码 -> 访问到用户主页(显示用户名) -> 修改密码(输入
原密码)-> 修改收货地址.......
问题:在此处登录会话过程中产生的数据(用户会话数据)如何保存下来呢?

购物场景:
打开浏览器 -> 浏览商品列表 -> 加入购物车(把商品信息保存下来) -> 关闭浏览器
打开浏览器-> 直接进入购物车 -> 查看到上次加入购物车的商品 -> 下订单 -> 支付
问题: 在购物会话过程中,如何保存商品信息?

以上场景都需要保留会话数据,需要会话管理机制。
会话管理: 管理浏览器客户端和服务器端之间会话过程中产生的会话数据。

为了会话管理,HTTP就需要传输大量重复信息内容的问题,造成大量的网络带宽消耗。于是 Cookie 和
Session 技术闪亮登场了,它们可以为用户进行会话管理,实现保存状态。

Cookie 又称为"小甜饼”。类型为"小型文本文件”,指某些网站为了辨别用户身份而储存在用户本地终端
(Client Side)上的数据(通常经过加密)。由网景公司的前雇员卢·蒙特利在1993年3月发明
因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的
实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于
HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么,所以Cookie就是用来绕开
HTTP的无状态性的"额外手段”之一。服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务
器会话中的状态。
在上面的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段
Cookie,记录着那项商品的信息。当用户访问另一个页面,浏览器会把Cookie发送给服务器,于是服务
器知道他之前选购了什么。用户继续选购饮料,服务器就在原来那段Cookie里追加新的商品信息。结帐
时,服务器读取发送来的Cookie就行了。
Cookie基于HTTP协议,也叫Web Cookie或浏览器Cookie,是服务器发送到用户浏览器并保存在客户端
本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它
用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie使基于无状态的HTTP
协议记录稳定的状态信息成为了可能。

#第一次请求过程
浏览器第一次发送请求时,不会携带任何cookie信息
服务器接收到请求之后,发现请求中没有任何cookie信息
服务器生成和设置一个cookie.并将此cookie设置通过set_cookie的首部字段保存在响应报文中返回给浏
览器
浏览器接收到这个响应报文之后,发现里面有cookie信息,浏览器会将cookie信息保存起来
#第二次及其之后的过程
当浏览器第二次及其之后的请求报文中自动 cookie的首部字段携带第一次响应报文中获取的cookie信息
服务器再次接收到请求之后,会发现请求中携带的cookie信息,这样的话就认识是谁发的请求了
之后的响应报文中不会再添加set_cookie首部字段

Cookie主要用于以下三个方面:

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

使用 Cookie 的状态管理

Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。当服务器收到HTTP请求
时,服务器可以在响应头里面添加一个Set-Cookie选项。浏览器收到响应后通常会保存下Cookie,之后
对该服务器每一次请求中都通过Cookie请求头部将Cookie信息发送给服务器。服务器端发现客户端发送
过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后
得到之前的状态信息.另外,Cookie的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。

Set-Cookie首部字段

NAME=VALUE 赋予 Cookie 的名称和其值,此为必需项
expires=DATE Cookie 的有效期,若不明确指定则默认为浏览器关闭前为止

会话期Cookie

基于内存保存,会话期Cookie是最简单的Cookie:浏览器关闭之后它会被自动删除,也就是说它
仅在会话期内有效。会话期Cookie不需要指定过期时间(Expires)或者有效期(Max-Age)。需
要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期Cookie也会
被保留下来,就好像浏览器从来没有关闭一样。

持久性Cookie

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

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

提示:当Cookie的过期时间被设定时,设定的日期和时间只与客户端相关,而不是服务端。

path=PATH 指定了主机下的哪些路径可以接受Cookie(该URL路径必须存在于请求URL中)。若
不指定则默认为文档所在的文件目录,以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。
例如,设置 Path=/docs ,则以下地址都会匹配:
/docs
/docs/Web/
/docs/Web/HTTP

domain=域名 指定了哪些主机可以接受Cookie。如果不指定,默认为当前文档的主机(不包含
子域名)。如果指定了Domain,则一般包含子域名。
例如,如果设置 Domain=longxuan.com,则Cookie也包含子域名(如:study.longxuan.com)

Secure 标记为 Secure 的Cookie只应通过被HTTPS协议加密过的请求发送给服务端。但即便设置
了 Secure 标记,敏感信息也不应该通过Cookie传输,因为Cookie有其固有的不安全性,Secure
标记也无法提供确实的安全保障。从 Chrome 52 和 Firefox 52 开始,不安全的站点(http:)无法使用Cookie的 Secure 标记。
HttpOnly 加以限制使 Cookie 不能被 JavaScript 脚本访问,为避免跨域脚本 (XSS) 攻击,通过JavaScript的 Document.cookie API无法访问带有 HttpOnly 标记的Cookie,它们只应该发送给服务端。如果包含服务端 Session 信息的 Cookie 不想被客户端 JavaScript脚本调用,那么就应该为其设置 HttpOnly 标记

浏览器对cookie的限制:

Cookie 存储的限制是不一样的。例如:单个域名可存储的 Cookie 数量、Cookie 大小等。
在进行页面 Cookie 操作的时候,应该尽量保证 Cookie 的个数小于 20 个,总大小小于 4KB,这是一个
安全且保险的范围。

范例:响应报文中的set-cookie首部

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

范例:请求报文中的cookie首部字段

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

范例:响应报文set-cookie中的Secure 和 HttpOnly

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

范例:php语言实现cookie的管理

#设置cookie
#cat setcookie.php
<?php
setcookie('title','cto'); #有效期为会话级
setcookie('user','wang',time()+3600*12); #有效期为12小时
echo "<h1>test setcookie </h1>"
?>
#说明:setcookie设置的cookie,只有下一次http请求才能生效
#显示cookie
cat showcookies.php
<?php
echo "<h1>test showcookie </h1>";
echo $_COOKIE["user"]; #显示user的这一个cookie
echo "<br />";
var_dump($_COOKIE); #显示所有cookie
//print_r($_COOKIE); #不如上面方式详细
?>
#删除cookie,通过设置过期时间实现
#vim delcookie.php
<?php
setcookie('user','wang',time()-3600*12);
echo "<h1>cookie:user is deleted </h1>";
?>

Session

session是相对于cookie的另外一个状态保持的解决方案,它是通过服务器来保持状态的。session指的
是服务器上为每个客户端所开辟的独立存储空间,在其中保存的信息就是用于保存状态的。
Session是服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建session的方法。在
创建了session的同时,服务器会为该session生成唯一的sessionId,而这个sessionId被创建了之后,
就可以调用session相关的方法往session中增加内容了,而这些内容只会保存在服务器中,每个
sessionid就像数据库中主键,可以根据SessionId 关联每个session的相关信息,比如:购物车里的商
器,登录用户等。但发送给客户端浏览器的只有sessionId。当客户端浏览器再次发送http请求时,会自
动地将这个sessionId 附加在请求报文中 ,服务器收到请求之后就会根据sessionId找到对应的
session,从而再次使用,使得用户的状态得以保持。

每个session都有一个sessionId,这个ID存放有两种方式:

1、通过URL存取,比如:Java程序中,URL会带上一个jsessionId=xxxxxx等,这样每次重新请求的时候都传了sessionId给服务器,但此方式不安全,所以很少使用,所以一般session是依赖于cookie的.即如果浏览器禁用了cookie,则session无法实现

2、通过cookie存取(Tomcat默认如此),这种cookie是session cookie,区别于persistent cookies也就是我们常说的cookie,session cookie要注意的是存储在浏览器内存中,而不是写到硬盘上。程序一开始执行,服务器就生成一个sessionId并通过cookie携带客户端浏览器的缓存中,当下一次访问的时候,服务器先检测一下是否有这个cookie,如果有就取它的ID,如果没有就再生成一个。这就是为什么关闭浏览器之后,再进去session已经没有了,其实在服务器端session并没有清空,而是sessionId变了。

当将浏览器关闭,服务器保存的session数据不是立即释放的,此时数据还会存在一段时间(可以在程序中加以设置,Tomcat默认15分钟),只要我们知道那个sessionId,就可以继续通过请求获得此session的信息。session里面的数据都放在服务器端,通过sessionId保证不会访问错误,服务端自动对session进行管理,如果在规定的时间内没有访问,则释放掉这个session。

最后提两点:
1、sessionId通常在浏览器地址中是看不到的,但是当我们把浏览器的cookie禁止之后,Web服务器会采用URL重写的方式传递sessionId,这样就可以在地址栏看到sessionId了

2、session cookie不可以跨窗口使用,但可以跨同一个窗口的多个标签页。

session 的工作流程

第一次请求:
浏览器发起第一次请求的时候可以携带一些信息(比如: 用户名/密码) cookie中没有任何信息
当服务器接收到这个请求之后,进行用户名和密码的验证,验证成功后则可以设置session信息
在设置session信息的同时(session信息保存在服务器端) .服务器会在响应头中设置一个随机的
session id的cookie信息
客户端(浏览器)在接收到响应之后,会将cookie信息保存起来(保存session id的信息)

第二次及其之后的请求:
第二次及其之后的请求都会携带session id信息
当服务器接收到这个请求之后,会获取到session id信息,然后进行验证
验证成功,则可以获取session信息(session信息保存在服务器端)

范例:PHP的PHPSESSID

<?php
session_start();
echo session_id();
?>
#执行浏览器结果可以看到效果

范例:JAVA的JSESSIONID

[root@centos8 ~]# cat /usr/local/tomcat/webapps/ROOT/session.jsp
<h1>
sessionId: <%=request.getSession().getId()%>
</h1>

cookie和session比较

cookie和session的相同和不同:

cookie通常是在服务器生成,但也可以在客户端生成,session是在服务器端生成的
session 将数据信息保存在服务器端,可以是内存,文件,数据库等多种形式,cookie 将数据保存在
客户端的内存或文件中
单个cookie保存的数据不能超过4K,每个站点cookie个数有限制,比如IE8为50个、Firefox为50
个、Opera为30个;session存储在服务器,没有容量限制
cookie存放在用户本地,可以被轻松访问和修改,安全性不高;session存储于服务器,比较安全
cookie有会话cookie和持久cookie,生命周期为浏览器会话期的会话cookie保存在缓存,关闭浏
览器窗口就消失,持久cookie被保存在硬盘,知道超过设定的过期时间;随着服务端session存储
压力增大,会根据需要定期清理session数据
session中有众多数据,只将sessionID这一项可以通过cookie发送至客户端进行保留,客户端下次
访问时,在请求报文中的cookie会自动携带sessionID,从而和服务器上的的session进行关联

cookie缺点:

1、使用cookie来传递信息,随着cookie个数的增多和访问量的增加,它占用的网络带宽也很大,试想假
如cookie占用200字节,如果一天的PV有几个亿,那么它要占用多少带宽?
2、cookie并不安全,因为cookie是存放在客户端的,所以这些cookie可以被访问到,设置可以通过插
件添加、修改cookie。所以从这个角度来说,我们要使用sesssion,session是将数据保存在服务端的,
只是通过cookie传递一个sessionId而已,所以session更适合存储用户隐私和重要的数据

session 缺点:

1、不容易在多台服务器之间共享,可以使用session绑定,session复制,session共享解决
2、session存放在服务器中,所以session如果太多会非常消耗服务器的性能
cookie和session各有优缺点,在大型互联网系统中,单独使用cookie和session都是不可行的
posted @ 2021-06-01 21:47  空白的旋律  阅读(552)  评论(0编辑  收藏  举报