Cookie和Session的原理及异同
1、Cookie:
Cookie是一种会话技术,它用于将会话过程中的数据保存到用户的浏览器中,从而使浏览器和服务器可以更好的进行数据交互。
1.1、Cookie的传输原理:
1)当用户第一次访问服务器时:服务器会在响应消息中增加Set-Cookie头字段
(Set-Cookie头字段的语法格式:Set-Cookie: CookieName=CookieValue; Path=/;),将用户信息以Cookie的形式发送给浏览器。
2)一旦用户浏览器接受了服务器发送的Cookie信息,就会将它保存在浏览器的缓存区中。
3)当浏览器后续访问服务器时,都会在请求消息中将用户信息以Cookie的形式发送给Web服务器,从而使服务器端分辨出当前请求是由哪个用户发出的。
2、Session:
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
2.2、Session原理:
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。
Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。相当于医院发放就诊卡,卡上只有卡号而没有其他信息。医生根据卡号在医院查询到病人的就诊信息。
需要注意的是,客户端需要接受、记录和回送Session对象的ID。
2.3、保存session id的几种方式:
A.保存session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。通常情况下,Session是借助Cookie技术来传递ID属性的。通过SessionID来区分不同的客户,默认使用cookie来实现,系统会自动创造一个名为JSESSIONID的输出返回给客户端Cookie保存。(session和cookie的关系——2.4)
B.由于cookie可以被人为的禁止,必须有其它的机制以便在cookie被禁止时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。
C.另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。
2.4:服务器是如何实现一个session为一个用户浏览器服务的?
服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。可以用如下的代码证明:
1 import java.io.IOException; 2 import javax.servlet.ServletException; 3 import javax.servlet.annotation.WebServlet; 4 import javax.servlet.http.Cookie; 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 /** 11 * Servlet implementation class TryCookieOfSession 12 */ 13 @WebServlet("/TryCookieOfSession") 14 public class TryCookieOfSession extends HttpServlet { 15 private static final long serialVersionUID = 1L; 16 17 /** 18 * @see HttpServlet#HttpServlet() 19 */ 20 public TryCookieOfSession() { 21 super(); 22 // TODO Auto-generated constructor stub 23 } 24 25 /** 26 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 27 */ 28 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 29 // TODO Auto-generated method stub 30 HttpSession session = request.getSession(); 31 32 if(session.isNew()){ 33 System.out.print("newly created: "); 34 System.out.println(session.getId()); 35 }else{ 36 System.out.println("aready have: "); 37 System.out.println(session.getId()); 38 39 Cookie[] cookie = request.getCookies(); 40 for(Cookie c : cookie){ 41 if(c.getValue().equals(session.getId())){ 42 System.out.println("cookie: " +c.getName() ); 43 } 44 } 45 } 46 //客户端再来的时候,服务器怎样判断服务器端有对应session 47 //服务器创建session并自动设置客户端cookie 48 //session是客户端自带的,还是服务器根据客户端cookie中的sessionID判断,然后返回服务器端的session 49 //如果客户端禁用了Cookie,那么每次服务器不能根据cookie从服务器端找session,每次都会创建一个新的session 50 51 //可以将登录信息保存在session域里(代表一次会话) 52 } 53 54 /** 55 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 56 */ 57 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 58 // TODO Auto-generated method stub 59 doGet(request, response); 60 } 61 62 }
尝试关闭cookie,看session每次请求是否能找到session:
结论:
客户端关闭cookie后,服务器端因为无法为一次会话创建一个cookie
无法判断每次来的请求是否来自同一个会话,所以会为每一次请求新创建session对象。
P.S:服务器端不用手动创建sessionID对于的COOKIE,
也不用判断根据每次请求客户端传来的cookie头中的sessionID从服务器端取对应的session,这些都是自动完成的。