JavaWeb——Cookie与Session机制
1、前言
Cookie与Session机制都是应用于Web开发的会话管理或会话跟踪中。最大的区别是:Cookie
是客户端(浏览器端)会话技术
,而Session
是服务端会话技术
,而。本篇文章将系统的说明Cookie与Session机制及其应用场景。
既然提到Cookie与Session机制都离不开"会话",那么首先来看一下什么是"会话"。
会话管理的产生
:由于HTTP的无状态性,使得会话管理或者会话跟踪成为Web应用开发一个无法避免的问题。默认情况一下,一个WEB服务器是无法区分一个HTTP请求是否为第一次访问。
会话
:一次会话中包含多次请求和响应
一次会话
:浏览器第一次给服务器发送请求,会话建立,直到有一方断开位置
会话的功能
:在一次会话的范围内的多次请求间共享数据
现在的JavaWeb项目要再谈及会话,一般就是这两种实现方式
● 客户端会话技术:Cookie
,将数据保存在客户端(浏览器)
● 服务端会话技术:Session
,将数据保存在服务器
2、Cookie
Cookie
:客户端会话技术,将数据保存在客户端(浏览器),Cookies是一个很少的信息片段,可自动地在浏览器和Web服务器间交互,因此Cookies可存储在多个页面间传递信息。Cookie作为HTTP header的一部分,其传输由HTTP协议控制,此外,可以控制Cookies的有效时间。浏览器通常支持每个网站高达20个Cookies。
2.1.Cookie的相关操作
服务端生成Cookie对象
Cookie cookie = new Cookie(String name,String value);
HTTP响应时会服务端会将Cookie对象发送(返回)给浏览器
response.addCookie(cookie);
服务端获取Cookie对象,由于Cookie没有提供直接根据name获取Cookie的方法,因此只能获取到所有的Cookie[],再根据name一个一个进行比较,最终找出该name所对应的value。
Cookie[] request.getCookies()
// 根据name一个一个进行比较
Cookie[] cookies = request.getCookies();
String name = "xxx";
String value;
if (cookies != null) {
for (Cookie c : cookies) {
if (c.getName().equals(name)) {
value = c.getValue();
}
}
}
删除Cookie,将name对应的value属性置为空,就相当于是删除,或者将Cookie的存活时间设置为0(Cookie立即过期),也相当于是删除。服务端删除Cookie
后需要给浏览器发送Cookie已被删除的结果(resp.addCookie(rmCookie));
)
// 将value置空
Cookie rmCookie = new Cookie(name, "");
// 将存活时间置0
rmCookie.setMaxAge(0);
// 向浏览器发送被删除的Cookie
resp.addCookie(rmCookie);
2.2.Cookie的实现原理
Cookie是一段文本信息。客户端第一次
请求服务器时,如果服务器需要记录用户状态,就在响应用户请求时发送一段Cookie信息。客户端浏览器保存该Cookie信息,当用户再次访问该网站时,浏览器会把Cookie做为请求信息的一部分提交给服务器。服务器检查Cookie内容,以此来判断用户状态,服务器还会对Cookie信息进行维护,必要时会对Cookie内容进行修改。(更多关于Cookie实现的文字描述请参考:Cookie实现原理)
只看文字会让人索然无味,因此还是放个图来更清晰的了解Cookie的实现原理。
这张图中就可以看出,Cookie的信息是保存在浏览器端
的。
2.3.Cookie的细节
2.3.1.服务器一次可不可以向浏览器发送多个Cookie
可以
,创建多个Cookie对象,使用response对象的addCookie()多次发送即可。
2.3.2.Cookie的生命周期(在浏览器中能保存多久)
默认情况下
,当浏览器关闭后
,Cookie数据被销毁
设置Cookie声明周期
,使Cookie持久化
用Cookie对象调用setMaxAge(int seconds)方法
正数:将Cookie数据写到硬盘文件中持久化存储,second表示cookie存活时间,单位是秒
负数:默认值为-1,存在浏览器内存中,浏览器一关闭就销毁Cookie数据
零:删除Cookie数据
2.3.3.Cookie的不可跨域名性
(Cookie共享问题)
Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。
Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作 Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名
。Google与Baidu的域名 不一样,因此Google不能操作Baidu的Cookie。
与之相同的,若在一个Tomcat服务器中部署了多个Web项目,那么在这些项目中Cookie是否共享?
默认情况下Cookie不能共享
setPath(String path):设置Cookie的获取范围,默认情况下设置当前项目的虚拟目录,如果要共享,则将path设置为:"/"。
不同的Tomcat服务器间Cookie共享问题
setDomain(String path):如果设置一级域名相同,那么多个服务器间Cookie共享
2.3.4.Cookie对中文的支持
在Tomcat8
之前,Cookie中不能直接存储中文(Cookie中保存中文只能编码。一般使用UTF-8编码即可),在Tomcat8之后,Cookie支持中文数据。
2.3.Cookie的特点
● Cookie存储的数据保存在浏览器中(客户端)
● 浏览器对于单个Cookie的大小有限制
(一般4K左右,和浏览器有关)以及对同一个域名下的总Cookie数量也有限制
(一般20个左右,和浏览器有关)
2.4.Cookie的作用
● Cookie一般用于存储少量的不太敏感的数据
● 用户免登录
(在不登录的情况下完成服务器对客户端的身份识别,主要作用)
3、Session
Session
:服务端会话技术,将数据保存在服务器,在一次会话的多次请求间共享数据。
HttpSession
:Servlet对Session机制的一种封装
3.1.HttpSession的相关操作
服务端获取Session对象,如果不存在就创建一个
HttpSession httpSession = request.getSession();
// 方法重载,如果没有,返回null
HttpSession httpSession = req.getSession(false);
// 方法重载,如果没有,创建一个
HttpSession httpSession = req.getSession(true);
服务端设置Session对象的值,需要注意的是,这里的value是Object
类型的,区别于Cookie只能使用String。因此Session可以存储任意类型
、任意大小
的数据。
httpSession.setAttribute(String name, Object value);
服务端获取Session对象的内容,比Cookie好在,Session可以通过name直接查找到对应的值。
Object value = httpSession.getAttribute(String name);
3.2.HttpSession的实现原理
所有保存在HttpSession的数据不会被发送到客户端,不同于其它会话管理技术, Servlet容器为每个 HttpSession生成唯一的标识, 并将该标识发送给浏览器,或创建一个名为JSESSIONID的cookie, 或者在 URL后附加一个名为jsessionid 的参数。 在后续的请求中,浏览器会将标识提交给服务端,这样服务器就可以识别该请求是由哪个用户发起的。 Servlet容器会自动选择一种方式传递会话标识,无须开发人员介入 。
与Cookie相同,只用文字描述会让人有种想撞墙的想法,因此也放个图了解一下HttpSession的实现原理。
3.3.Session的细节
3.3.1.当客户端关闭后,服务器不关闭,两次获取Session是否为同一个
● 默认情况下,不是同一个
● 若想要实现相同,则需要自行创建一个Cookie,该Cookie的name为JSESSIONID(name必须是这个),value为session.getId(),并设置该Cookie的最大存活时间,使得Cookie持久化保存。(虽然session默认生成的Cookie随着浏览器的关闭而销毁,但通过自定义相同的JSESSIONID,从而实现两次访问相同的session
,至少,这两次访问是在session还未过期时,若session已过期,就不能实现相同了
)
//希望客户端关闭后再次获取Session能相同
Cookie cookie = new Cookie("JSESSIONID",session.getId());
cookie.setMaxAge(60 * 60);
response.addCookie(cookie);
3.3.2.客户端不关闭,服务器关闭后,两次获取的Session是否为同一个
● 默认情况下,不是同一个
● 要确保数据不丢失(session的钝化和活化——Tomcat已经完成了钝化和活化工作,具体钝化活化细节请参考:Session的活化与钝化)
● session的
钝化
:当服务器正常关闭时,还存活着的session(在设置时间内没有销毁) 会随着服务器的关闭被以文件(“SESSIONS.ser”)的形式存储在tomcat 的work 目录下。
● session的活化
:当服务器再次正常开启时,服务器会找到之前的“SESSIONS.ser” 文件,从中恢复之前保存起来的Session 对象。
● 想要随着Session 被钝化、活化的对象它的类必须实现Serializable 接口
● I注意:DEA可以完成钝化但是无法活化成功,要依靠本地的Tomcat服务器去完成钝化和活化,但是实际开发中也不会在IDEA里面部署项目,所以关系不大。
3.3.3.HttpSession的生命周期(Session什么时候被销毁)
● 默认情况下是30分钟(容器的配置),可修改Tomcat容器的默认配置(具体操作如下)
● 手动设置当前程序session的过期时间
// 1、web.xml配置文件中更改配置信息
<session-config>
<session-timeout>20</session-timeout>
</session-config>
// 2、调用setMaxInactiveInterval()方法,在用户30分钟之内无活动,设置过期,单位秒
httpSession.setMaxInactiveInterval(60 * 30);
● 手动设置session立即过期(一般用于用户退出登录时,代码中人为设置过期)
httpSession.invalidate();