Cookie 与 Session 是很常用的实现 Http 状态的技术,在不断的使用中,自己也对其有所理解。我接下来的讨论,是基于下面的顺序:
1、为什么要使用 Cookie 和 Session
由于 Http 协议的请求过程,是基于 TCP/IP 的,当客户端请求服务器,服务器处理后,进行响应,这个过程是无状态的。在有些时候,是需要保存一些客户端的请求信息,识别客户端的某些状态,智能的、有针对性的去分析某些客户端的习惯。这些时候,就需要去记录客户端的连接状态,识别请求的状态等。为了解决类似的事情,就需要使用到了 Cookie 和 Session。
2、Cookie 和 Session 的具体知识
(1)Cookie:在客户端访问某个地址时,会将请求交到服务器进行处理,在发送请求的时候,浏览器会将页面的头部信息一并的交到服务器端进行处理。在处理的过程中,Cookie 在服务器端生成 ,在此同时,可以将一些需要保存的信息,存放到此 Cookie 中。生成 Cookie 对象时,需要确定具体的名称及具体的值,可以设置当前 Cookie 的过期时间,设置过期时间后,就相当于持久化了 Cookie 中的数据,此时的 Cookie 会以之前的 Cookie 名称,保存在客户端。
如果不设置过期时间,则当前 Cookie 的生命期是浏览器会话期间,一旦关闭了该浏览器,当前的Cookie 就会不存在了,此时的 Cookie 信息是保存在内存中。在服务器端,处理完后,会将生成的 Cookie ,随着 Http 响应,会在 Http 响应头中,加上Cookie 信息,浏览器接受到响应后,会按照 Http 响应头里的 Cookie ,在客户端建立 Cookie 。在下次客户进行请求的时候,Http 会附带着已经存储过的 Cookie,一并发送到服务器。一个域,在客户端建立的所以 Cookie 都是可以共享的,只要 Cookie 没有过期。
(2)Session:Session 是在服务器端生成的,存储在服务器端,即存在内存中。可以对生成的 Session 设置过期时间,如果不设置过期时间,默认的 Session 过期时间是30 分钟(在不同的服务器中,它的过期时间略有不同,本文是以 Tomcat 来说的) 但是,Sesssion 的生成的同时,会生成一个与之相关联的的 SessionID ,此 SessionID的存储是需要 Cookie 来完成的。 SessionID 是以名称为 JSESSIONID,其值应该是一个既不会重复,又不容易被找到规律以仿造的字符串。SessionID会随着此次 Http 响应,一并返回到客户端,并保存在客户端中。到当前请求再次发出后,该 SessionID会随着 Http 头部,传到服务器中,服务器依据当前 SessionID 得到与之对应的 Session.
其中:通过 Cookie 的方式存储 Session 状态,只是其中一种方式。如果客户端禁用了 Cookie 的话,很多网站任然可以存储用户的信息。一种处理的方式是URL 重写,将 SesseionID 直接附加在请求地址的后面。另一种处理的方式是,使用隐藏自动的方式。就是服务器自动的在表单中,添加一个隐藏字段,以便在表单提交时,将 SesseionID 一起传到服务器,进行识别。
3、Cookie 和 Session 的具体使用
最近,我在写一个代码生成器的时候,我希望在我填写完数据库连接信息后,浏览器帮我把这些信息保存起来,以免每次我需要使用的时候,都去填写,浪费时间。下面是我具体的做法:
/** * 存储数据库连接对象 * @param database 数据库连接对象 * @param request http 请求对象 * @param response http 响应对象 * @param jonArray 数据库中的所有表和 JSONArray 对象 * @return null 空 */ private String storeDatabaseInfo(Database database, HttpServletRequest request, HttpServletResponse response, JSONArray jonArray) { /* * 判断: * (1)如果 session 存在并且存储过 database 数据,则不再进行重复保存 * (2)如果,没有,则将数据存储到 Session 中 */ HttpSession session = request.getSession(false); if(session != null && session.getAttribute("database") != null){ //(1)如果 session 存在并且存储过 database 数据,则不再进行重复保存 log.info("当前回话已经保存过 databse 的数据了,不再进行重复的保存!"); }else{ //(2)如果,没有,则将数据存储到 Session 中 session.setAttribute("database", database); session.setMaxInactiveInterval(60*60); } /* * 判断: * (1)如果 request 中保存过,则不再进行重复保存 * (2)如果,没有,则将数据存储到 Cookie 中 */ Cookie[] cookies = request.getCookies(); if((cookies != null)){ for (Cookie cookie : cookies) { if (cookie.getName().equals("database")) { log.info("当前Cookie 中,已经保存过 databse 的数据了,不再进行重复的保存!"); //(1)如果 request 中保存过,则不再进行重复保存 return jonArray.toString(); } } } //(2)如果,没有,则将数据存储到 Cookie 中 String databaseInfoStr = database.getDatabaseType() + "_" + database.getUrl() + "_" + database.getPort() + "_" + database.getUser() + "_" + database.getPassword() + "_" + database.getDatabaseName() + "_" + database.getTable(); Cookie databaseInfo = new Cookie("database", databaseInfoStr); databaseInfo.setMaxAge(60*60); //设置 Cookie 的过期时间 databaseInfo.setHttpOnly(true); //设置 Cookie 的使用协议 databaseInfo.setPath("/CodeGenerator/"); //设置 Cookie 的使用域 response.addCookie(databaseInfo); return null; }
其中:特别注意的是,在生成 Cookie 后,如果不设置当前 Cookie 的使用,无论有没有设置 Cookie 的过期时间,当下次访问的时候,都是获取不到该名称对应的 Cookie 的。如果设置databaseInfo.setPath(“/”)使用在全局的环境中,所有的请求都可以使用该 Cookie , 如果设置和项目相关的域,如:databaseInfo.setPath(“/CodeGenerator/”),在只会在当前项目的访问下使用当前 Cookie 。
(4)Cookie 和 Session 的区别
首先,Cookie 是存储在客户端的,Session 是存储在服务器端的。
其次,对安全性要求低的情况下,可以考虑使用 Cookies,在相对安全性要求高的信息时候,可以考试使用 Session。毕竟 Cookie 存在客户端,其他人可以查找并分析的。
最后,在对性能要求高的时候,不适合使用 Session 的,因为 Session 会一直存在服务器的,直到当前 Session 过期,而且 Cookie 存储是字符串类型的信息,而 Session 可以存储任何形式的信息,Session 也不存在访问域的限制。
个人觉得,在存储相对持久的信息时,应考虑使用 Cookie,因为 Cookie 可以以文件的形式,存储在客户端。在进行一些登录的验证及信息拦截的时候,可以使用 Session。