说到cookie和session先从二者的英文单词含义说起,cookie翻译为中文是小饼干的意思,session翻译成中文是会话的意思。从翻译就能看出来,cookie是服务器返回给浏览器的一些断断续续的东西,而session是一种会话机制。那么为什么要用cookie和session呢?
- 因为Http协议是一种无状态协议,服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session,而session是如何实现状态保持的呢?
- 这个时候cookie作用就体现出来了!
- 每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。
总结一下:
- Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
- Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
- Cookie保存在客户端,只能保存字符串对象,不能保存对象类型,需要客户端浏览器的支持:客户端可以不支持,因为浏览器用户可能会禁用Cookie。
- 每次客户端发送请求,服务断都检查是否含有sessionId。如果有,则根据sessionId检索出session并处理;如果没有,则创建一个session,并绑定一个不重复的sessionId。 状态信息保存在服务器端。这意味着安全性更高,通过类似与Hashtable的数据结构来保存, 能支持任何类型的对象(session中可含有多个对象) 。
- 浏览器第一次创建session的代码
//获取session的Id
String sessionId = session.getId();
//将session的Id存储到名字为JSESSIONID的cookie中
Cookie cookie = new Cookie("JSESSIONID", sessionId);
//设置cookie的有效路径
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
问题:因为用户浏览器唯一的sessionId是通过cookie带到服务端的,那么当浏览器禁用cookie怎么办?
- 解决:进行访问浏览器的url进行重写:
response.encodeRedirectURL(java.lang.String url) //用于对sendRedirect方法后的url地址进行重写。
response.encodeURL(java.lang.String url) //用于对表单action和超链接的url地址进行重写
具体使用:
public class IndexServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
//创建Session
request.getSession();
out.write("本网站有如下书:<br/>");
Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();
for(Map.Entry<String,Book> me : set){
Book book = me.getValue();
String url =request.getContextPath()+ "/servlet/BuyServlet?id=" + book.getId();
//response. encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写
url = response.encodeURL(url);//将超链接的url地址进行重写
out.println(book.getName() + " <a href='"+url+"'>购买</a><br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
当浏览器禁用了cookie后,就可以用URL重写这种解决方案解决Session数据共享问题。而且response. encodeRedirectURL(java.lang.String url)
和response. encodeURL(java.lang.String url)是两个非常智能的方法,当检测到浏览器没有禁用cookie时,那么就不进行URL重写了。
- Session对象的创建和销毁:
1.在程序中第一次调用request.getSession()方法时就会创建一个新的Session,可以用isNew()方法来判断Session是不是新创建的
2.session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 设置Session的有效时间:以分钟为单位-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session。
代码如下:
HttpSession session = request.getSession();
//手工调用session.invalidate方法,摧毁session
session.invalidate();
小结:
如上文所述,session和cookie的目的相同,都是为了克服http协议无状态的缺陷,但完成的方法不同。session通过cookie,在客户端保存session id,而将用户的其他会话消息保存在服务端的session对象中,与此相对的,cookie需要将所有信息都保存在客户端。因此cookie存在着一定的安全隐患,例如本地cookie中保存的用户名密码被破译,或cookie被其他网站收集。