会话技术cookie和session详解
Posted 我和Messi五五开
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了会话技术cookie和session详解相关的知识,希望对你有一定的参考价值。
什么是会话
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
会话技术解决了什么问题
每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据。
例如:用户点击超链接通过一个servlet购买了一个商品,程序应该保存用户购买的商品,以便于用户点结帐servlet时,结帐servlet可以得到用户商品为用户结帐。
会话技术分类
会话技术会为两类
- Cookie
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
- Session
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
一定要知道会话技术能解决什么问题才能学以致用。cookie用途典型的例子是保持登录状态,下次进入网页不用再次登录。session典型例子是显示在线总人数,购物车的实现等。
ookie介绍
什么是cookie
Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。
Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,对于JSP而言也可以直接写入jsessionid,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等,服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。
Cookie与http协议
- Cookie与http协议关系
Cookie是Http协议制定的,并不是Java语言独有的,PHT、.NET中也使用了cookie技术,因此只要是和HTTP协议相关,那么就可以使用cookie技术。
我们知道cookie是服务器创建的一个键值对,并保存在浏览器端。那么服务器是如何将cookie发送给浏览器的呢?
在服务器端先创建cookie,如 Cookie cookie=new Cookie(String name,String value),其中Cookie可以在javaeeAPI中查到的,详情可参考java_ee API。然后再通过response对象将cookie信息作为响应头发送到浏览器端。我们可以通过HttpWatch抓包工具查看响应信息,可以发现cookie是基于一个Set-Cookie响应头工作的,由于Set-Cookie响应头可以有多个,所以我们可以通过response.addHeader(String name,String value)方法发送Set-Cookie响应头,例如,有两个cookie,分别为one=aaa,two=bbb,其中one、two是cookie的名称,aaa、bbb是cookie的值。发送响应头如下所示:
response.addHeader(“Set-Cookie”,”one=aaa”);response.addHeader(“Set-Cookie”,”two=bbb”);
当浏览器再次访问服务器时,会将cookie送还给服务器。那么浏览器是如何将cookie带给服务器的呢?其实通过Cookie请求头传递过去的。请求头Cookie与响应头Set-Cookie有区别,多个cookie对应多个Set-Cookie响应头,但是只对应一个Cookie请求头,格式为:Cookie:one=aaa; two=bbb。即多个cookie之间用分号和空格隔开。
需要注意的是:cookie是不能跨浏览器的。例如,张三首先使用IE浏览器访问服务器,服务器发送了一个cookie,这个cookie只会保存在IE浏览器,如果再使用火狐浏览器访问服务器,服务器会再发送一个cookie个火狐浏览器,在火狐浏览器中不能获取IE浏览器中的cookie,同理IE浏览器也获取不到火狐浏览器中的cookie。
- http协议规定
Http协议对Cookie做了一些规定,如下所示:
一个Cookie的大小,最大为4KB;
一个服务器最多向一个浏览器保存20个Cookie;
一个浏览器最多可以保存300个Cookie。
我们知道,浏览器将服务器发送过来的cookie保存在本地磁盘,如果cookie过多,必然会加大浏览器的压力,因此Http协议对Cookie做了以上规定。
但是,目前浏览器之间因为竞争,很多都在一定范围内违反了Http规定,例如,一个浏览器最多保存的Cookie个数超过300个。但是也不会出现浏览器允许一个Cookie的大小超过4kB。
cookie常用API及原理
cookie相关API
javax.servlet.http.Cookie类用于创建一个Cookie,response接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。Cookie类的方法:
构造方法
- public Cookie(String name, String value)
构造带指定名称和值的 cookie。
成员方法
- public String getName()
返回 cookie 的名称
- public String getValue()
返回 cookie 的值。
- public void setMaxAge(int expiry)
设置 cookie 的最大生存时间,以秒为单位
- public void setPath(String uri)
指定客户端应该返回 cookie 的路径。
cookie示例
在day1114工程下创建一个CookieDemo1Servlet,写入以下代码:
//1.创建cookie
Cookie cookie=new Cookie("cookieName","cookieValue");
//2.通过response对象将cookie响应到浏览器
response.addCookie(cookie);
cookie原理
通过抓包工具我们在次分析一下关于cookie的原理
- 当在浏览器上访问http://localhost/day1114/cookieDemo1
- 抓取到的http请求与响应信息如下:
http请求信息
GET /day1114/cookieDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
http响应信息
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: cookieName=cookieValue
Content-Length: 0
Date: Tue, 12 May 2015 05:26:53 GMT
http请求信息
GET /day1114/cookieDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
Cookie: cookieName=cookieValue
通过以上分析,我们通过下面图进行总结:
持久化cookie
Cookie持久化
如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用Cookie类的setMaxAge方法,并给出一个以秒为单位的时间。
删除持久cookie,可以将cookie最大时效设为0,注意,删除cookie时,path必须一致,否则不会删除
-1代表的是浏览器关闭后失效.
Cookie路径
Cookie的路径是在服务器创建Cookie时设置的,它的作用是决定浏览器访问服务器的某个资源时,需要将浏览器端保存的那些Cookie归还给服务器,可以通过Cookie类的setPath方法来设置cookie的路径.
关于路径包含关系
例如,浏览器中保存如下几个cookie,它们的路径分别是:
aCookie.path=/day10/;bCookie.path=/day10/jsps/;cCookie.path=/day10/jsps/cookie
访问路径是:http://localhost:8080/day10/index.jsp
浏览器发送给服务器的cookie有:aCookie;
访问路径是:http://localhost:8080/day10/jsps/a.jsp
浏览器发送给服务器的cookie有:aCookie,bCookie;
访问路径是:http://localhost:8080/day10/jsps/cookie/b.jsp
浏览器发送给服务器的cookie有:aCookie,bCookie,cCookie。
cookie案例-记录上次访问时间
功能描述
当访问day10工程下的某一个servlet时,会显示出上一次访问这个资源的时间。
案例分析
- 流程分析
-
Ø 使用到的知识点分析
n Cookie cookie=new Cookie(); 创建cookie
n response.addCookie() 将cookie添加到http响应中
n request.getCookies(); 获取所有的cookie
代码实现
VisitServlet
public class VisitServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.得到系统当前时间
Date date=new Date();
//2.创建一个cookie
Cookie cookie=new Cookie("time",date.getTime()+"");
//3.将 cookie通过response响应到浏览器端
response.addCookie(cookie);
}
}
ShowTimeServlet
public class ShowTimeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置响应编码
response.setContentType("text/html;charset=utf-8");
//1.得到名称叫time的cookie
Cookie[] cs = request.getCookies();
//2.遍历cs,得到cookie
for(Cookie c:cs){
if("time".equals(c.getName())){//判断cookie的名称是否有叫time
long time=Long.parseLong(c.getValue()); //得到名称叫time的cookie的value
Date date=new Date(time); //构造出新的时间
response.getWriter().write(date.toLocaleString());
return;
}
}
response.getWriter().write("第一次访问:"+new Date().toLocaleString());
}
}
我们可以将上述两个servlet合成一个servlet处理。
public class ShowCurrentTimeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.设置响应编码
response.setContentType("text/html;charset=utf-8");