用户打开浏览器—使用浏览器—到关闭的整个过程。
是web程序中常用的技术,用来跟踪用户的整个会话,常用的会话跟踪技术是Cookie与Session 。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
一个用户的所有请求操作都应该属于同一个会话。
是使用HTTP协议传输数据。HTTP协议是无状态的协议,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接,这就是意味着服务器无法从连接上跟踪会话
给客户端们办法一个通行证,每人一个,无论谁访问都必须携带自己通行证,这样服务器就能从通行证上确认客户身份了
(1)浏览器端第一次发送请求到服务器端
(2)服务器端创建Cookie,该Cookie中包含用户的信息,然后将该Cookie发送到浏览器端
(3)浏览器端再次访问服务器端时会携带服务器端创建的Cookie
(4)服务器端通过Cookie中携带的数据区分不同的用户
public class ServletContext06 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器告诉你,你第一次来把时间封装成一个信件,下次带着信件访问服务器就知道是你来了
//解决文中乱码
req.setCharacterEncoding("utf-16");
resp.setCharacterEncoding("utf-16");
//创建一个输出流对象
PrintWriter out=resp.getWriter();
//Cookie是服务器从客户端获取到的
Cookie[] cookies=req.getCookies();//可能获取到多个Cookie
//判断Cookie是否存在
if (cookies!=null){
out.write("你上一次访问的时间是:");
for (int i=0;i<cookies.length;i++){
Cookie cookie=cookies[i];
//判断cookie的名字是否是lastLoginTime,为了找到指定的cookie
if (cookie.getName().equals("lastLoginTime")){
//获取cookie的值
long lastLoginTime=Long.parseLong(cookie.getValue());
Date date=new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else{
out.write("这是你第一次访问本网站");
}
//服务器给客户端响应一个新cookie,名字叫做lastLoginTime
Cookie cookie=new Cookie("lastLoginTime",System.currentTimeMillis()+"");
resp.addCookie(cookie);
}
}
//cookie有效期为1天
cookie.setMaxAge(24*60*60);
Session域就是另一种会话技术,也叫做服务器端技术。Session的底层也是基于Cookie的,只不过有自己的改变。
(1)浏览器端第一次发送请求到服务器端,服务器端创建一个Session,同时会创建一个特殊的Cookie(name为jessionID(好像是cookieID一样的唯一标识的东西)的固定值,value为session对象的ID),然后将该Cookie发送至浏览器端
(2)浏览器端发送第N(N>1)次请求到服务器端,浏览器端访问服务器端时就会携带该name为jessionID的Cookie对象
(3)服务器端根据name为jessionID的Cookie的value(sessionID),去查询Session对象,从而区分不同用户。
name为jessionID的Cookie不存在(关闭或更换浏览器),返回1中重新去创建Session与特殊的Cookie
name为jessionID的Cookie存在,根据value中的SessionId去寻找session对象。
value为SessionId不存在(Session对象默认存活30分钟),返回1中重新去创建Session与特殊的Cookie
value为SessionId存在,返回session对象
Session的工作原理图
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决文中乱码
req.setCharacterEncoding("utf-16");
resp.setCharacterEncoding("utf-16");
resp.setContentType("utf-16");
//得到session
HttpSession session=req.getSession();
//给session存东西
session.setAttribute("name","manman");
//获取sessionID
String sessionId=session.getId();
//判断session是否新建
if (session.isNew()){
resp.getWriter().write("session创建成功。ID:"+sessionId);
}else {
resp.getWriter().write("session已经在服务器存在。ID:"+sessionId);
}
//session创建的时候做了什么事
Cookie cookie=new Cookie("JESSIONID",sessionId);
resp.addCookie(cookie);
}
//网页1——保存一个对象
//得到session
HttpSession session=req.getSession();
//给session存东西
session.setAttribute("name",new GetServlet("manamnzi",1));
//网页2——读取对象
HttpSession session=req.getSession();
GetServlet name=(GetServlet)session.getAttribute("name");
System.out.println(name.toString());
//手动注销
session.removeAttrbute("name");
session.invalidate();
//设置session默认的失效时间——在web.xml中
<session-config>
<!--15分钟后自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
session
简单的说,当你登陆一个网站的时候,如果web服务器端使用的是session,那么所有的数据都保存在服务器上,客户端每次请求服务器的时候会发送当前会话sessionid,服务器根据当前sessionid判断相应的用户数据标志,以确定用户是否登陆或具有某种权限。由于数据是存储在服务器上面,所以你不能伪造。
cookie
sessionid是服务器和客户端连接时候随机分配的,如果浏览器使用的是cookie,那么所有数据都保存在浏览器端,比如你登陆以后,服务器设置了cookie用户名,那么当你再次请求服务器的时候,浏览器会将用户名一块发送给服务器,这些变量有一定的特殊标记。服务器会解释为cookie变量,所以只要不关闭浏览器,那么cookie变量一直是有效的,所以能够保证长时间不掉线。
如果你能够截获某个用户的cookie变量,然后伪造一个数据包发送过去,那么服务器还是 认为你是合法的。所以,使用cookie被攻击的可能性比较大。
如果cookie设置了有效值,那么cookie会保存到客户端的硬盘上,下次在访问网站的时候,浏览器先检查有没有cookie,如果有的话,读取cookie,然后发送给服务器。
所以你在机器上面保存了某个论坛cookie,有效期是一年,如果有人入侵你的机器,将你的cookie拷走,放在他机器下面,那么他登陆该网站的时候就是用你的身份登陆的。当然,伪造的时候需要注意,直接copy cookie文件到 cookie目录,浏览器是不认的,他有一个index.dat文件,存储了 cookie文件的建立时间,以及是否有修改,所以你必须先要有该网站的 cookie文件,并且要从保证时间上骗过浏览器
两个都可以用来存私密的东西,session过期与否,取决于服务器的设定。cookie过期与否,可以在cookie生成的时候设置进去。
用在网上购买东西这个案例来剖析这个问题。
如果说,我要去购买一件上衣向服务器发送一个购买请求,它返回给我一个购买成功的响应;当我再去购买一个裤子的时候就相当于又一个请求,那么这时候用转发的话当然就不行了,如果用重定向的话可以解决这个问题,只不过比较麻烦。然后把里面所购买的上衣的数据从request域拿出来和第二个请求拼接在一起在存入request域中。
但是当我要去结算的,就是在另一个Servlet中,这个时候我的request域中的数据就会全部丢失。具体如下图所示:
这两个域在我看来没有本质上的区别,可以理解为服务器端的共享空间。只不过说,ServletContext域表示的是整个web服务,而pageContext域表示的是一次请求。
如果说,我要购买一件上衣,向服务器发送一个请求,服务器返回给我一个购买成功的请求 ,同样的再去购买一条裤子也是一样的。看来一切都是正常的,结算也可以去结算界面结算我的总金额。
但是,我要说的是,因为这是一个购物界面,所以就不会只是你一个用户。因为这是一个服务器端的共享空间,所以当别人也去购买东西添加购物车后,你去结算的时候就包括自己和别人共同的东西。具体如下图所示:
同样去买一件上衣,这个时候就会把上衣这个对象存入的开辟的Cookie空间中, Cookie空间为此对象绑定一个唯一的标识然后以响应头方式返回给客户端,当再去购买裤子的时候会带着这个唯一标识以请求头的方式存入到Cookie空间中,同时为它绑定唯一的标识。因为Cookie域保存在自己浏览器内部,与别人互不干扰,但因为是客户端技术,所以安全性不高。具体如下图所示:
和Cookie一样,去买一件上衣,这个时候就会把上衣这个对象存入的开辟的Session空间中, Session空间为此对象生成一个唯一的Key值,当再去购买裤子的时候会带着这个唯一的Key值存入到Cookie空间中,同时为它绑定唯一的Key值。因为Session域同样保存在自己浏览器内部,与别人互不干扰,它相较于Cookie而言是服务器技术,较安全。具体如下图所示: