2017年9月11日 上午9:23
概述
我结合我昨天看的一个电影加勒比海盗5-死无对证来说明我对cookie和session的理解吧。
电影中的小男主角在自己还是一个小屁孩的时候,去荷兰号去找父亲,父亲当时将自己脖子中的项链 给了小男主角,就是希望有一天等小男主角长大之后还可以相认。果然,那主角不负众找到了三叉戟,破除了海洋中的所有诅咒。最后,小男主角和父亲相见的时候,父亲第一眼看的是哪个项链,然后确认了之后他们拥抱在一起(ps:关键是小男主角还找了一个漂亮的媳妇,bravo!)
先说cookie
这里的项链就是我们这里的一个cookie,cookie由服务器产生,cookie在给了客户端之后服务器就没有了 (给了儿子,父亲自然就没了),由于http是无状态的,所以一旦下一次访问(男主就和父亲很难相见),服务器是不认识谁了,但是客户端有了这个cookie,服务器就根据这个cookie知道你是你是谁了,这两个人就相认了。
这里有几个特殊情况,例如这个cookie让别人拿走 ,用在了其他的浏览器上,那么服务器也是不知道了(这样父亲就认错孩子了),但是利用这种情况,可以做多个客户端浏览器的同步。还有就是一个服务器可以为很多不同的用户服务(父亲有好多的孩子,都给了他们不同的项链),服务器在把自己的cookie给出去之后,其实对于自己产生的cookie的具体内容也不知道了 ,他得根据客户端给他啥,他就知道啥,认为这就是自己给客户端的,简单的说:给啥我要啥(这一点的判断是浏览器根据访问的url来划分的,浏览器访问不同的url,会把不同的url对应的cookie全都传过去),这也就解决了一个服务器多个客户端的问题,客户端给我啥我要啥,这时候可以理解成的情景是:就是两个人在普通的交流,这个交流就一个回合,但是客户端这人用本子记录内容,但是服务器这个人比较懒 。
对于服务器来说,只要有人访问他,他就给他一个cookie,其中就是一个Jsessionid 。对于双11来说,你想想他会产生多少个Jsessonid,服务器这么做的原因是想和各种来找他的人都建立起关系,维护住关系。
cookie中还有一个domain 的概念,我理解就是兄弟姐妹之间公用一个cookie作为信物 ,而不是每个人一个。
还要就是session
Session是保存在服务端 ,这个可以理解成父亲在根据cookie认出自己的儿子之后,从自己的记忆中找到了很多自己和儿子相处的儿时时光,这只有父亲一个知道,其他人根本不知道,是私有的。这里的私有记忆就是session ,只能让服务器自己程序执行的时候使用,作为自己一些功能实现的判断依据,用来写代码逻辑用的 。
这里还说明了其实session和cookie其实是完全不同的东西 。他们之间的联系是当一个 Session 开始时,Servlet 容器将创建一个 HttpSession 对象,Servlet 容器为 HttpSession 分配一个唯一标识符,称为 Session ID ,这个sessionid是一个cookie ,是为了让服务端能够区分开不同的用户 ,那么根据这个cookie就可以在服务端的代码逻辑中过滤一些人(eg:防止用户没登录就访问购物车界面,然后告知他没登录)。这一点也可以从javaEE手册中证明,session和cookie是没有继承和实现关系的。
其他:
session服务器内存中 cookie客户端硬盘中
Session的有效时间通过xml控制,而cookie直接通过代码控制
Tomcat自带一个web.xml文件,如我们在使用session中没有在自己的项目web.xml中声明有效时间,那么默认使用就是tomcat中web.xml文件的
在禁止使用cookie的地方使用session
response.encodeURL的用法 - zhaogengzi的专栏 - CSDN博客
response.encodeURL的用法 - langqiao123的专栏 - CSDN博客
可以从http报文头中去观察cookie的过程
详细的知识点 直接看这个txt文档排版比较整齐,下面那个是为了方便粘贴复制cookie和session.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 ================================ ================================ ================================ 会话跟踪 1 . 什么是会话 * 用户拨打10086 ,从服务台接通后会话开始; * 用户发出话费查询请求,服务台响应。这是该会话中的一个请求; * 用户发出套餐变更请求,服务台响应。这是该会话中的又一个请求; * ... * 用户挂断电话,会话结束。 2 . 会话的特性 * 一个会话中可能包含多个请求; * 一个会话中发出请求的用户是唯一的; 3 . JavaWeb会话 * 从用户打开本站第一个页面开始,会话也开始了; * 用户会发出0 ~n个请求; * 用户关闭浏览器会话结束了。 4 . 什么是会话跟踪技术 HTTP是无状态协议,也就是没有记忆力的协议,每个请求之间无法共享数据。 这就无法知道会话什么时候开始,什么时候结束,也无法确定发出请求的用户身份。这说明需要使用额外的手段来跟踪会话! * 在一个会话中共享数据即会话跟踪技术 ------------------------------------ Cookie 1 . 什么是Cookie* Cookie是HTTP协议的规范之一,它是服务器和客户端之间传输的小数据。 * 首先由服务器通过响应头把Cookie传输给客户端,客户端会将Cookie保存起来。 * 当客户端再次请求同一服务器时,客户端会在请求头中添加该服务器保存的Cookie,发送给服务器。 * Cookie就是服务器保存在客户端的数据! * Cookie就是一个键值对!!! 2 . Cookie规范* Cookie通过请求头和响应头在服务器与客户端之间传输; * Cookie大小限制在4 KB之内; * 一台服务器在一个客户端最多保存20 个Cookie; * 一个浏览器最多可以保存300 个Cookie; 虽然Cookie规范是如此,但在今天,浏览器厂商的竞争异常激烈,所以多少会超出Cookie规则的限制。但也不会超出过多! 3 . Cookie与请求头和响应头* 服务器向客户端发送Cookie的响应头为Set-Cookie,例如:Set-Cookie:cookiename=cookievalue * 客户端向服务器发送Cookie的请求头为Cookie,例如:Cookie:cookiename=cookievalue 4 . Servlet中向客户端发送Cookie Cookie cookie1 = new Cookie("test1" , "abcdefg" ); Cookie cookie2 = new Cookie("test2" , "ABCDEFG" ); response.addCookie(cookie1); response.addCookie(cookie2); 5 . Servlet中获取客户端发送过来的Cookie Cookie[] cs = request.getCookies(); if (cs != null ) { for (Cookie c : cs) { System.out.println(c.getName() + "=" + c.getValue()); } } ============================= Cookie的细节 1 . Cookie的maxAge 当服务器创建Cookie对象后,可以调用setMaxAge()方法设置Cookie的最大生命。 * maxAge > 0 :表示Cookie在客户端硬盘上保存的最大时间,单位为秒; * maxAge < 0 :表示Cookie不会被浏览器保存到硬盘上,而只在浏览器内存中存活,一旦客户端关闭浏览器在,那么Cookie就消失; * maxAge == 0 :表示删除Cookie,例如客户端硬盘已经存在名为abc的Cookie,如果服务器再向客户端发送名为abc,并且maxAge为0 的Cookie,那么表示删除客户端上的名为abc的Cookie。 2 . Cookie的path 浏览器在访问BServlet时,是否要带上AServlet保存的Cookie呢?这要看Cookie的path了。 现有资源如下: * http: * http: * http: * http: AServlet { Cookie c = new Cookie("xxx" , "XXX" ); response.addCookie(c); } CServlet { Cookie c = new Cookie("yyy" , "YYY" ); c.setPath="/day06_2" ; response.addCookie(c); } DServlet { Cookie c = new Cookie("zzz" , "ZZZ" ); resposne.addCookie(c); } 在BServlet中保存的Cookie没有设置path,那么它的path默认为当前BServlet的所在路径,即“/day06_2/servlet”。 在CServlet中保存的Cookie设置了path为/day06_2。 在DServlet中保存的Cookie没有设置path,那么它的path默认为DServlet的所在路径,即“day06_2/servlet/user” 当访问AServlet时,是否要带上xxx这个Cookie呢?因为AServlet的访问路径为/day06_2/servlet/BServlet,它包含了xxx的path,即/day06_2/servlet,所以需要带上。 当访问AServlet时,是否要带上yyy这个Cookie呢?因为AServlet的访问路径为/day06_2/servlet/BServlet,它包含了xxx的path,即/day06_2,所以需要带上。 当访问AServlet时,是否要带上zzz这个Cookie呢?因为AServlet的访问路径为/day06_2/servlet/BServlet,它不包含zzz的path,即/day06_2/servlet/user,所以不会带上。 3 . Cookie的domain Cookie的path是在同一主机中指定共享Cookie,如果主机不同那么就一定不能共享Cookie,无论path是什么。 如果希望不同的二级域名中可以共享Cookie,那么就要设置Cookie的domain了。 例如:news.baidu.com、tieba.baidu.com、zhidao.baidu.com,它们的域名不同,但百度希望它们之间可以共享Cookie,那么就要设置domain了。 1 ). 设置Cookie的path为“/”,例如:cookie.setPath("/" ); 2 ). 设置Cookie的domain,例如:cookie.setDomain(".baidu.com" ),其中domain中没有指定域名前缀! 在news.baidu.com主机中的某个项目中保存了Cookie 在tieba.baidu.com主机中某个项目中获取Cookie 当然这需要配置两个虚拟主机才行。 4 . Cookie保存中文 Cookie的name和value都是不能保存中文的,但可以先把中文转换成URL编码,然后在保存到Cookie的name和value中。 String name = "姓名" ; String value = "张三" ; name = URLEncoder.encode(name, "utf-8" ); value = URLEncoder.encode(value, "utf-8" ); Cookie c = new Cookie(name, value); response.addCookie(c); 在获取Cookie时,再使用URL解码即可。 Cookie[] cs = request.getCookies(); if (cs != null ) { for (Cookie c : cs) { byte [] b=c.getName().getBytes(iso-8859 -1 ); String name = new String(b,"utf-8" ); String name = URLDecoder.decode(c.getName(), "utf-8" ); String value = URLDecoder.decode(c.getValue(), "utf-8" ); System.out.println(name + "=" + value); } } ============================= ============================= ============================= HttpSession 在JavaWeb中提供了HttpSession类,用来表示http会话。 1 . 获取HttpSessionHttpSession session = request.getSession(); HttpSession session = request.getSession(false ); 2 . 域功能 session是域对象,所以有setAttribute()和getAttribute()等方法 服务器会为每个会话创建一个session对象,所以session中的数据可供当前会话中所有servlet共享。 3 . 登录案例 请求功能: 1 . 如果登录功能,在session中保存user对象 2 . 访问index1.jsp,查看session中是否存在user对象,如果存在,说明已经登录过。 3 . 访问index2.jsp,查看session中是否存在user对象,如果存在,说明已经登录过。 如果关闭了浏览器,那么会话结束,再打开浏览器就开始了一个新会话,那么直接访问index1.jsp或index2.jsp时,session是新的,没有保存user对象,那么表示还没有登录。 4 . session的原理 session是依赖Cookie实现的。 session是服务器端对象 当用户第一次使用session时(表示第一次请求服务器),服务器会创建session,并创建一个Cookie,在Cookie中保存了session的id,发送给客户端。这样客户端就有了自己session的id了。但这个Cookie只在浏览器内存中存在,也就是说,在关闭浏览器窗口后,Cookie就会丢失,也就丢失了sessionId。 当用户第二次访问服务器时,会在请求中把保存了sessionId的Cookie发送给服务器,服务器通过sessionId查找session对象,然后给使用。也就是说,只要浏览器容器不关闭,无论访问服务器多少次,使用的都是同一个session对象。这样也就可以让多个请求共享同一个session了。 当用户关闭了浏览器窗口后,再打开浏览器访问服务器,这时请求中没有了sessionId,那么服务器会创建一个session,再把sessionId通过Cookie保存到浏览器中,也是一个新的会话开始了。原来的session会因为长时间无法访问而失效。 当用户打开某个服务器页面长时间没动作时,这样session会超时失效,当用户再有活动时,服务器通过用户提供的sessionId已经找不到session对象了,那么服务器还是会创建一个新的session对象,再把新的sessionId保存到客户端。这也是一个新的会话开始了。 设置session超时时间 web.xml文件中配置如下: <session-config> <session-timeout>30</session-timeout> </session-config> 5 . session与浏览器 session对象是保存在服务器端的,而sessionId是通过Cookie保存在客户端的。 因为Cookie不能在多个浏览器中共享,所以session也不能在多个浏览器中共享。也就是说,使用IE登录后,再使用FireFox访问服务器还是没有登录的状态。 而且同时打开多个相同浏览器的窗口,是在使用同一session。如果你使用的是老浏览器,例如IE6,那么就会每个窗口一个session。 6 . session的API * String getId () :获取sessionId; * int getMaxInactiveInterval () :获取session可以的最大不活动时间(秒),默认为30分钟。当session在30分钟内没有使用,那么Tomcat会在session池中移除这个session; * void setMaxInactiveInterval (int interval) :设置session允许的最大不活动时间(秒),如果设置为1秒,那么只要session在1秒内不被使用,那么session就会被移除; * long getCreationTime () :返回session的创建时间,返回值为当前时间的毫秒值; * long getLastAccessedTime () :返回session的最后活动时间,返回值为当前时间的毫秒值; * void invalidate () :让session失效!调用这个方法会被session失效,当session失效后,客户端再次请求,服务器会给客户端创建一个新的session,并在响应中给客户端新session的sessionId; * boolean isNew () :查看session是否为新。当客户端第一次请求时,服务器为客户端创建session,但这时服务器还没有响应客户端,也就是还没有把sessionId响应给客户端时,这时session的状态为新。 7. URL重写 session依赖Cookie,这是因为服务器需要把sessionId保存到客户端。如果用户的浏览器关闭了Cookie功能,那么session不能使用了! 还可以在浏览器关闭了Cookie后使用URL重写的方法保存sessionId,这需要在每个URL后面都加上sessionId!这样用户的请求中就包含了sessionId,服务器就可以通过sessionId找到对应的session对象了。 使用response.encodeURL () 方法对URL进行编码,这样URL中会智能的添加sessionId。 当浏览器支持cookie时,response.encodeURL () 方法不会在URL后追加sessionId 当浏览器不支持cookie时,response.encodeURL () 方法会在URL后追加sessionId