Session


Session

Cookie技术可以将用户的信息保存在各自的浏览器中,

优点:很明显实现了同一个用户不同请求中数据共享。

缺点:黑客可以利用脚本等手段 窃取cookie中的重要数据,从而泄漏个人的隐私,存在巨大的安全隐患。

session技术 是将会话的数据保存在服务器端的技术。

3.1.什么是session?

为了更好的理解session,以网站购物为例,通过一张图来描述session保存用户 信息的原理。

用户甲和用户乙都调用buyServlet将商品添加到购物车,调用payServlet进行商品结算。

由于甲和乙购买商品类似,这里以甲为主。

当用户甲访问购物网站时,服务器为甲创建了一个session对象(相当于购物车)。

当甲将小米手机添加到购物车时,小米手机的信息便存到了session对象中,同时,服务器将session对象的唯一标识id属性以Cookie的形式返回给甲的浏览器。

当甲完成购物进行结账时,需要向服务器结账请求,这时,浏览器就会自动在请求头将 唯一标识 回送给服务器。

服务器根据唯一标识,找到为用户甲创建的session容器,并将session对象中存放的手机信息进行结算。

Session_第1张图片
Session_第2张图片

需要注意的是:由于客户端需要接受、记录、和回送session的唯一标识,

因此通常情况下,session是借助cookie技术来传递ID属性的。

3.1.SessionAPI

3.1.1.获取Session对象

Session是基于用户的请求,而把用户的重要信息在服务器端针对这个用户(浏览器)创建了一个容器。

而这个Session容器是由web服务器(tomcat)帮助我们创建的,在程序中我们只能去获取到这个容器,然后给容器添加数据或者取出数据,或者删除数据,而我们是不能创建这个容器对象。

在HttpServletRequest对象中提供了获取session对象的方法:

使用request对象就可以获取到当前针对用户的请求服务器内部创建的那个Session容器对象。

HttpSession依然是一个接口,而这个接口的实现类有web服务器来提供。只要能够运行我们JavaEE项目的web访问前,它们都会实现Java提供的所有web技术中的接口。

演示Session:

需要2个Servlet程序:

在第一个Servlet中获取到Session对象,然后把用户当前的ip保存在Session中,在第二Servlet中取出,然后通过response对象把ip给客户端响应回去。第一个Servlet访问完之后,不使用转发技术。

给Session对象中保存数据:

需要使用HttpSession接口中的:

获取数据:

删除Session中的数据

需求1: 共享数据:第一个Servlet程序:获取到用户的ip保存在Session中;在第二个servlet中取出session中的ip(debug演示)

Session_第3张图片

3、新建Session2Servlet,从session中获取ip

Session_第4张图片

4、通过浏览器直接访问Session2Servlet,能够看到ip吗?

看不到,原因:还没有向session容器中存放ip。

5、通过浏览器先访问Session1Servlet,再访问Session2Servlet,能看到ip地址吗? 能

Session_第5张图片
Session_第6张图片

3.2.2.服务器端操作Session时细节

Session_第7张图片

其实服务器端可以识别每个用户的对应的Session容器,主要是因为服务器针对每个用户都发送了JSESSIONID(session容器的唯一标识)的Cookie信息。这样用户在操作的时候,都会携带这个Cookie到服务器端,因此服务器端才能识别针对当前这个用户的那个session容器对象。


服务器在给客户端响应数据的时候,把Session容器的唯一标识以Cookie的形式发送给浏览器,而这个Cookie是一个会话级别(临时)Cookie,它只能存活在浏览器运行的阶段,如果浏览器关闭了,这个Cookie信息就没有了,因此在此打开浏览器访问的时候,就不会在服务器获取到针对当前用户的JSESSIONID信息,因此无法找到针对当前用户的那个Session容器。

进一步说明,服务器端的Session容器对象,是针对每个浏览器的。

3.2.3.使用getSession方法的细节

在api中提供2个获取Session对象的方法:

getSession():

空参数的方法,在使用的时候,如果服务器端针对当前用户的浏览器没有Session容器,这时在服务器的内部会先创建一个Session对象,然后把这个Session对象返回给我们的程序。

如果Session容易已经存在,这时它是不会再创建新的Session容器对象,只是把找到的这个Session容器对象返回给程序。在找的过程中需要依赖于JSESSIONID。

getSession(Boolean create):

如果这个在调用的时候,传递的值为false,它仅仅只会在容器根据JSESSIONID找有没有对应的Session容器对象,如果有就返回这个Session容器对象,如果没有,就返回null。

如果传递的值true,在根据JSESSIONID找Session容器对象的时候,如果不存在就会创建一个新的Session容器对象,并返回这个容器对象,如果存在就,直接返回存在的Session容器对象。

3.3.思考:关闭浏览器后再次访问能获取到Session的数据吗?

一般情况下,关闭浏览器之后,再次访问,是无法获取到Session中的数据的。

因此在服务器针对当前用户的第一次请求创建的唯一的Session容器对象,而在给这次请求的之后,服务器需要给用户响应数据,在响应的时候,服务器把当前Session容器对象的JSESSIONID以Cookie的形式发送给了浏览器。而这个Cookie并没有设置有效时间,那么这个Cookie就属于临时Cookie,在关闭浏览器之后,再次打开浏览器的时候,上次的Cookie已经消失了,用户虽然拿同一个浏览器访问服务器,可是这时没有JSESSIONID,服务器端的Session容器依然存在,但是没有JSESSIONID,服务器内部无法获取到这个session对象

把包含了JSESSIONID的Cookie在客户端持久化。

Session_第8张图片

3.4.禁用Cookie后Session追踪

服务器端获取Session对象依赖于客户端携带的Cookie中的JSESSIONID数据。如果用户把浏览器的隐私级别调到最高,这时浏览器是不会接受Cookie、这样导致永远在服务器端都拿不到的JSESSIONID信息。这样就导致服务器端的Session使用不了。

Java针对Cookie禁用,给出了解决方案,依然可以保证JSESSIONID的传输。

Java中给出了再所有的路径的后面拼接JSESSIONID信息。

使用response对象中的方法完成:

需求3:浏览器禁用cookie,当前servlet的session中设置ip,超链接跳转另一个servlet时可以获取ip地址。

1在Session1Servlet中,使用response.encodeURL(url)对超链接路径拼接 session的唯一标识

2使用浏览器访问

在response对象中的提供的encodeURL方法它只能对页面上的超链接或者是form表单中的action中的路径进行重写(拼接JSESSIONID)。

如果我们使用的重定向技术,这时必须使用下面方法完成:

1在Session1Servlet的基础上增加如下代码:

其实就是在路径后面拼接了Session的唯一标识 JSESSIONID。

3.5.Session的生命周期(面试

Session对象的创建时间:

当前服务器启动之后,用户第一次访问某个Servlet程序的时候,在这个Servlet中调用getSession()方法或者调用的getSession(true),这时服务器内部才会针对当前这个用户的浏览器创建一个Session容器对象。

Session的销毁时间:

1、不正常关闭服务器。如果是正常关闭服务器,这时服务器内部会使用IO流中的序列化技术把这个Session对象保存在tomcat/work目录下面。

2、Session在服务器的存活时间。Session对象在服务器内部有默认的存活的时间。一般默认是30分钟。如果在30分钟内,用户没有再对当前这个服务器中的资源进行任何的访问操作,这时只要时间到达30分钟,服务器会自动的销毁这个session。

Session的存活时间我们可以在当前这个项目的web.xml中配置:

Session_第9张图片

3、调用HttpSession中的销毁Session的方法:

3.1.Session案例一次性验证码登录

验证码的实现原理:

在一个Servlet中生成验证,并把验证码上的数据保存在Session,用户提交验证码之后,会提交给另外一个Servlet程序。在获取用户提交数据的Servlet中的从Session中把验证码取出,在取出的同时从Session中把验证码删除。

注册页面:register.jsp

Session_第10张图片

生成验证码参考:cn.itcast.session.CheckImgServlet

publicclassCheckImgServletextendsHttpServlet {

publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {

intwidth = 120;

intheight = 40;

// 先生成一张纸

BufferedImage bufi =newBufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

// 画笔

Graphics g = bufi.getGraphics();

// 设置背景颜色

// 修改画笔颜色

g.setColor(Color.white);

// 填充

g.fillRect(0, 0, width, height);

// 绘制边框

// 设置边框颜色

g.setColor(Color.red);

// 画边框

g.drawRect(0, 0, width - 1, height - 1);

// 准备一些数据

String data ="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz";

// 生成随机对象

Random r =newRandom();

String checkcode ="";

// 生成4个随机的数字

for(inti = 0; i < 4; i++) {

// 生成随机颜色

g.setColor(newColor(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

// 设置字体

g.setFont(newFont("宋体", Font.ITALIC, 25));

String c = data.charAt(r.nextInt(data.length())) +"";

g.drawString(c, 10 + (20 * i), 30);

checkcode += c;

}

// 将生成的验证码放到 session中

request.getSession().setAttribute("session_checkcode", checkcode);

// 画干扰线

for(inti = 0; i < 8; i++) {

// 设置随机颜色

g.setColor(newColor(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

// 画线 两点确定一线

g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));

}

// 将图片输出到浏览器

ImageIO.write(bufi,"jpg", response.getOutputStream());

}

publicvoiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, IOException {

}

}

注册servlet:

Session_第11张图片

3.1.Servlet三种数据范围

下面的三个对象,可以当做容器来使用,可以保存数据,因此他们也被称为域对象。

ServletContext:它保存的数据所有的Servlet共享。它的范围最大。开发几乎不用。除非需要保存整个项目中共享的信息才会使用。

HttpSession:它是针对当前某个用户(浏览器)的一系列操作,然后在服务器端创建的一个容器,整个容器仅仅只能是当前这个客户端(浏览器)使用。多个客户端(浏览器),它们会有不同的Session容器对象

HttpServletRequest:它的针对用户的这次请求,只要请求和响应结束,这个容器就消失了。一般开发中这个容器是最常用。只要给request中保存了数据之后,那么就会使用转发技术,转发到JSP页面上,在页面上使用EL表达式把request中的数据取出,并显示。

你可能感兴趣的:(Session)