Cookie 和 Session

Posted qqiua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cookie 和 Session相关的知识,希望对你有一定的参考价值。

  在Web应用中,一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应的过程称为一个会话(如一个用户在某购物网站上的整个购物过程就是一个会话)。在整个会话过程中,客户端与服务器端的交互会产生一些数据,而Web服务器需要对这些数据进行保存。在Servlet技术中,主要提供两个用于保存会话数据的对象,分别是Cookie和Session。

1 Cookie 对象                                                                                        

  Cookied主要用于将会话保存到用户的浏览器中,从而使浏览器和服务器可以更好地进行数据交互

  Cookie是浏览器端使用的一种记录用户状态的机制,它实际上是一小段保存在浏览器中的文本信息。当客户端通过浏览器请求服务器时,如果服务器需要记录该用户的状态,就会使用response对象向客户端浏览器颁发一个Cookie,客户端浏览器会把Cookie保存起来。当通过浏览器再次请求该网站时,浏览器会把请求的网址连同该Cookie一同提交给服务器,服务器会检查该Cookie,以此辨认用户状态。

  服务器向客户端发送Cookie时,会在HTTP响应头字段中增加Set-Cookie响应头字段。语法格式:

Set-Cookie: user=admin; path=/;

user:表示Cookie名称;
admin: 表示Cookie的值;
Path:表示Cookie的属性

Cookie在浏览器和服务器之间的传输过程如下图:

  当用户第一次通过浏览器访问服务器时,服务器会在响应消息中加入Set-Cookie头字段,将用户信息以Cookie的形式发给浏览器。用户浏览器接收了服务器发送的Cookie信息,就会将它保存在浏览器的缓冲区中,这样,当浏览器后续访问该服务器时,会在请求消息中将用户信息以Cookie的形式发送给Web浏览器,从而使服务器端分标出当前请求是由哪个用户发出的。

技术分享图片

1.1 Cookie API

  Java中的javax.servlet.http.Cookie类用于创建一个Cookie

Cookie类的主要方法

No.

方法

类型

描述

1

Cookie(String name, String value)

构造方法

实例化Cookie对象,传入Cookie名称和Cookie的值

2

public String getName()

普通方法

用于返回Cookie的名字

3

public String getValue()

普通方法

用于返回Cookie的值

4

public void setValue(String newValue)

普通方法

用于为Cookie设置一个新的值

5

public void setMaxAge(int expiry)

普通方法

用于设置Cookie子浏览器客户机上保持有效的秒数。即Cookie的有效期,当服务器给浏览器回送一个Cookie时,如果在服务器端没有调用setMaxAge方法设置Cookie的有效期,那么Cookie的有效期只在一次会话过程中有效,用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一次会话,当用户关闭浏览器,会话就结束了,此时Cookie就会失效,如果在服务器端使用setMaxAge方法设置了Cookie的有效期,比如设置了30分钟,那么当服务器把cookie发送给浏览器时,此时Cookie就会在客户端的硬盘上存储30分钟,在30分钟内,即使浏览器关了,Cookie依然存在,在30分钟内,打开浏览器访问服务器时,浏览器都会把Cookie一起带上,这样就可以在服务器端获取到客户端浏览器传递过来的Cookie里面的信息了,这就是Cookie设置maxAge和不设置maxAge的区别,不设置maxAge,那么Cookie就只在一次会话中有效,一旦用户关闭了浏览器,那么Cookie就没有了,那么浏览器是怎么做到这一点的呢,我们启动一个浏览器,就相当于启动一个应用程序,而服务器回送的Cookie首先是存在浏览器的缓存中的,当浏览器关闭时,浏览器的缓存自然就没有了,所以存储在缓存中的Cookie自然就被清掉了,而如果设置了Cookie的有效期,那么浏览器在关闭时,就会把缓存中的cookie写到硬盘上存储起来,这样Cookie就能够一直存在了。

6

public int getMaxAge()

普通方法

用于返回Cookie子浏览器客户机上保持有效的秒数

7

public void setPath(String uri)

普通方法

设置Cookie的有效路径,比如把Cookie的有效路径设置为"/xdp",那么浏览器访问"xdp"目录下的web资源时,都会带上Cookie,再比如把cookie的有效路径设置为"/xdp/gacl",那么浏览器只有在访问"xdp"目录下的"gacl"这个目录里面的web资源时才会带上Cookie一起访问,而当访问"xdp"目录下的web资源时,浏览器是不带cookie的

8

public String getPath()

普通方法

获取Cookie的有效路径

9

public void setDomain(String pattern)

普通方法

 设置Cookie的有效域

10

public String getDomain()

普通方法

 获取Cookie的有效域

1.2  示例: 显示用户上次访问的时间

 1 package cn.cookie;
 2 import java.io.IOException;
 3 import java.text.SimpleDateFormat;
 4 import java.util.Date;
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.Cookie;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class cookie1 extends HttpServlet {
12     private static final long serialVersionUID = 1L;
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         //设置服务器端以UTF-8编码进行输出
16         response.setCharacterEncoding("UTF-8");
17         //设置浏览器以UTF-8编码进行接收,解决中文乱码问题
18         response.setContentType("text/html; charset=UTF-8");
19         String lastAccessTime=null;
20         Cookie[] cookies = request.getCookies();
21         for(int i=0; cookies!=null && i<cookies.length; i++){
22             if("lastAccess".equals(cookies[i].getName())){
23                 lastAccessTime = cookies[i].getValue();
24                 break;
25             }
26         }    
27         if(lastAccessTime == null){
28             response.getWriter().print("您是首次访问本站");
29         }else{
30             response.getWriter().print("您上次访问的时间是:"+lastAccessTime);
31         }
32         //创建cookie,将当前时间作为cookie的值发送给客户端
33         String currentTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
34         Cookie cookie = new Cookie("lastAccess", currentTime);    
35         response.addCookie(cookie);
36     }    
37     public void doPost(HttpServletRequest request, HttpServletResponse response)
38             throws ServletException, IOException {
39         
40     }
41 }

第一次访问,运行结果:

技术分享图片

刷新后:

技术分享图片

在上面的例子中,在程序代码中并没有使用setMaxAge方法设置cookie的有效期,所以当关闭浏览器之后,cookie就失效了,要想在关闭了浏览器之后,cookie依然有效,那么在创建cookie时,就要为cookie设置一个有效期。

在34行后添加如下代码

//设置Cookie的有效期为1天
cookie.setMaxAge(24*60*60);

这样即使关闭了浏览器,下次再访问时,也依然可以通过cookie获取用户上一次访问的时间。

 1.3 Cookie注意细节

  (1)一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。

  (2)一个Web站点可以给有个Web浏览器发送多个Cookie,一个Web浏览器也可以存储多个Web站点提供的Cookie。

  (3)浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4kb。

  (4)如果创建了一个cookie,并将他发送给浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器中),用户推出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAges,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。

1.4 Cookie中存取中文

  要想在cookie中存储中文,那么必须使用URLEncoder类里面的encode(String s, String enc)方法进行中文转码,例如:

1 Cookie cookie = new Cookie("userName", URLEncoder.encode("您好,哈哈", "UTF-8"));
2 response.addCookie(cookie);

在获取cookie中的中文数据时,再使用URLDecoder类里面的decode(String s, String enc)进行解码,例如:

URLDecoder.decode(cookies[i].getValue(), "UTF-8")

 

2 Session 对象                                                                                                       

  Session是服务器端使用的一种记录客户端状态的机制。当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,当客户端后续访问服务器时,只要将标识(ID)号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之响应的Session对象并为其服务。

2.1 Session API

  由于Session是与每个请求消息紧密相关的,因此,在HTTPServletRequest中定义了用于获取Session对象的getSession方法,该方法两种重载形式:

public HttpSession getSession(boolean create);
public HttpSession getSession();

//第一个getSession()方法根据传递的参数判断是否创建新的HttpSession对象,如果参数为true,则在相关的HttpSession对象不存在时返回新的HttpSession。否则不创建。
//第二中方法getSession()相当于第一个方法参数为true的情况。

注意:由于getCookie()方法可能会产生发送会话标号的Cookie头字段,因此必须在发送任何响应内容之前调用getSession()方法。

HttpSession接口的常用方法:

方法声明 功能描述
Sting getId() 用于返回与当前HttpSession对象关联的会话标识号
long getCreationTime() 返回Session创建的时间。这个时间是创建Session的时间与1970年1月1日0时0分0秒之间时间差的毫秒标识形式
long getLastAccessedTime() 返回客户端最后一次发送与Session相关请求的时间。如上
void setMaxInactiveInterval(int interval) 用于设置当前HttpSession对象可空闲的以秒为单位最长的时间,也就是修改当前会话的默认超时间隔
vboolea isNew() 判断当前HttpSession对象是否是新创建的
void invalidate() 用于强制使Session对象无效
ServletContext getServletContext() 用于返回当前HttpSession对象所书序的Web应用程序对象,即代表当前Web应用程序的ServletContext对象
void setArribite(String name, Object value) 用于将一个对象与一个名称关联后存储到当前的HttpSession对象中
String getArribute() 用于从当前HttpSession对象中返回指定名称的属性对象
void removeAttribute(String name) 用于从当前HttpSession对象中删除指定名称属性

 2.2 Session保存用户信息过程

  由于客户端需要接收、记录和回送Session对象的ID,因此,在通常情况下,Session是借助Cookie技术传递ID属性的。以网站购物为例,以下为Session保存用户信息的原理。

技术分享图片

  浏览器A和浏览器B都调用buyServlet将商品添加到购物车,然后调用payServlet进行商品结算。A和B购买过程类似。当浏览器A访问购物网站时,服务器为用户甲创建了一个Session对象(相当于购物车)。当浏览器A将vivo添加到购物车时,vivo的信息会存放到Session对象中,同时,服务器会将Session对象的ID属性以Cookie(Set-Cookie:JSESSION=111)的形式返回给浏览器。当浏览器A完成购物并进行结账时,需要想服务器发送结账请求,这时,浏览器将自动在请求消息头中将Cookie(Set-Cookie:JSESSION=111)信息发送给服务器,服务器会根据ID属性找到浏览器A所创建的Session对象,并将Session对象存放的vivo信息取出并进项结算。

 2.3 服务器实现一个session为一个用户浏览器服务

  服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号器,服务器发现客户机浏览器带session id过来了,就会使用与之对应的session为值服务。

 1 package cn.cookie;
 2 
 3 import java.io.IOException;
 4 import javax.servlet.ServletException;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import javax.servlet.http.HttpSession;
 9 
10 public class session1 extends HttpServlet {
11     private static final long serialVersionUID = 1L;
12     public void doGet(HttpServletRequest request, HttpServletResponse response)
13             throws ServletException, IOException {
14         response.setCharacterEncoding("UTF=8");
15         response.setContentType("text/html;charset=UTF-8");
16         //使用request对象的getSession()获取session,如果session不存在则创建一个
17         HttpSession session = request.getSession();
18         session.setAttribute("data", "没有耳朵的猫");
19         String sessionId = session.getId();
20         if(session.isNew()){
21             response.getWriter().print("session创建成功,session的id是:"+sessionId);
22         }else{
23             response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
24         }
25         
26     }
27     
28     public void doPost(HttpServletRequest request, HttpServletResponse response)
29             throws ServletException, IOException {    
30     }
31 
32 }

第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,如下图所示:

技术分享图片

点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的Id一起传递到服务器端了,如下图所示:

技术分享图片

 

 2018-10-08 11:42:24

 

以上是关于Cookie 和 Session的主要内容,如果未能解决你的问题,请参考以下文章

少部分手机浏览器对于COOKIE支持不够导致服务端无法读取session的解决方案

Cookie和Session的工作流程及区别(附代码案例)

cookie和session

cookie和session

cookie和session

会话技术知识点整理(Cookie和Session)