会话管理之Session

来源:互联网 发布:linux telnet命令 编辑:程序博客网 时间:2024/05/16 10:36

1.会话控制

  • HTTP协议是一个无状态协议,我们服务器不能区分多次请求是否发送自一个浏览器。

  • 目前使用Cookie来解决这个问题,Cookie实际上就是一个头,服务器以响应头的形式将Cookie发送给浏览器浏览器收到该头以后,会将Cookie的信息保存,然后在每次访问服务器时,会以请求头的形式将Cookie发回。

Cookie的局限性:

1.Cookie是纯文本,非常容易被截获,不太安全。
2.各个浏览器对Cookie的数量和大小都有限制,也就是说我们不能再Cookie中保存过多的信息。
3.即使对Cookie大小没有限制,我们也不会在Cookie中保存大量信息,因为浏览器每次访问时都会发回Cookie,这样会占用大量带宽。

[1] HttpSession

简介

  • HttpSession运行时依赖于Cookie

  • session是JavaWeb中四个域对象之一

  • Cookie中的信息是保存到浏览器端,但是浏览器每次访问时都需要发回Cookie,所以我们不能再Cookie中保存大量的信息

  • 既然客户端不能保存大量的信息,可不可以将信息保存到服务器中呢?

  • 所以我们可以为每次会话都在服务器中创建一个对象,然后在对象中保存相关的信息。

  • 会话 –> 对象

  • 对象就是HttpSession

  • 怎么给会话和对象建立一个对应关系?

  • 每一个session对象都有一个id,这个id是不可重复的,也就是每一Session对象都有一个唯一的标识。

  • 那么我们就可以将这个唯一的标识交个浏览器保存,浏览器每次访问服务器时都会带着这个唯一标识,这样我们就可以根据这个id找到浏览器对应的session对象。

工作机制(掌握)

  • HttpSession对象就相当于浏览器在服务器的账户,而session的id,相当于这个账户的账号(JSESSIONID)

  • 实际上HttpSession对象就是服务器中用来保存会话信息的对象,每个session对象都有一个唯一的id。这个id通过cookie的形式发送给浏览器,浏览器收到cookie以后会自动保存。然后在每次访问服务器时,都会带着这个Cookie,服务器就可以根据Cookie中保存session的id找到浏览器对应的session对象。

Cookie的具体形式如下:

Cookie: JSESSIONID=A1C1D6E213BDF1F147E673963ED503B2

  • 一次会话对应一个session对象

  • session对象是什么时候创建的?

HttpSession对象在getSession()方法第一次被调用时创建

HttpSession创建时都会有一个JSESSIONID,服务器会将session对象保存到一个SessionMap中

这个map的key就是JSESSIONID,而value就是session对象

如果浏览器在访问服务器时携带JSESSIONID这个Cookie,服务器不会再去创建新的Session对象,而是根据浏览器的JSESSIONID的值,去SessionMap中去查找已有的Session对象。
- 在JSP对应的Java文件已经自动调用getSession()方法,所以我们在访问JSP时也会创建session对象

有效时间

  • session的默认有效时间为一次会话,也就是说关闭浏览器以后session中的属性将会丢失。

  • 之所以默认时间是一次会话,并不是因为HttpSession对象被销毁,而是因为浏览器保存的那个JSESSIONID的那个Cookie没了。

  • 尝试着创建一个关闭浏览器后依然有效的Session?

设置JSESSIONID这个Cookie的有效时间,来达到即使关闭浏览器Session依然有效的目的,但是,我们说这种做法,没有实际意义,主要是用来了解Session的工作机制。

  • HttpSession对象都是保存到服务器的SessionMap中的,一旦Session对象闲置超过一定时间以后,服务器会自动将该对象销毁,那这样以后即使浏览器还保存着JSESSIONID,但是由于对象已经销毁了,所以这时服务器以后重新创建一个新的HttpSession对象。

  • 我们要如何来设置Session的最大闲置时间?

我们可以通过session.getMaxInactiveInterval()来获取session的最大闲置时间

1.我们可以通过修改web.xml配置文件的方式

1) 在总的web.xml文件中有如下配置信息:

  • 将session的默认闲置时间设置为30分钟

30

  • 我们可以通过修改该值,来修改有效时间,但是在总的web.xml文件修改,会导致当前服务器下的所有项目的session的闲置时间都会被修改。

2) 也可以在当前项目的web.xml文件中设置,设置方法和上边一样

30

2.可以通过调用session对象方法的形式来设置:

session.setMaxInactiveInterval(秒数);

大于0的时间

  • 会设置闲置时间为相应的秒数

等于0的时间

  • 会使session对象立即失效

session.invalidate();也可以使session立即失效

小于0的时间

-如果给setMaxInactiveInterval方法设置一个负的时间,则session对象永远不会被销毁

判断session对象是否是新创建的:

session.isNew()

URL重写 (理解)

  • HttpSession运行时依赖于Cookie

  • 如果我们将浏览器的Cookie禁用,那么HttpSession将不同正常使用。

  • 因为浏览器如果禁用了Cookie则保持着JSESSIONID的那个Cookie,浏览器将不会保存,也就是说浏览器每次访问服务器时候都没有JSESSIONID,所以Session对象将不能正常使用。

  • 目前我们的Cookie都是通过请求报文的请求头来传送,我们可不可以通过URL地址来传递请求参数呢?

JSESSIONID=29BAA3DDCCD6563ECE852D78E76EDC54

传递的方式

http://localhost:8080/12_WEB_Session/hello.jsp;jsessionid=29BAA3DDCCD6563ECE852D78E76EDC54

这种方式就叫做URL重写,但是我们手动拼地址很不靠谱。

1.通过调用response的方法

 String url = response.encodeURL(request.getContextPath()+"/hello.jsp");

【encodeURL方法:Encodes the specified URL by including the session ID in it, or, if encoding is not needed, returns the URL unchanged】

String url2 = response.encodeRedirectURL(request.getContextPath()+”/hello.jsp”);
【encodeRedirectURL:deprecated】

2.通过JSTL中的url标签

整体来说URL重写是比较简单,但是我们在实际开发中对URL重写做的并不是很多,一般情况下如果浏览器将Cookie禁用,那么一些依赖于Session功能也将失效,URL重写以后的地址,容易泄露信息,不太安全!

Session的活化和钝化 (了解)

  • 钝化

指将HttpSession对象序列化到硬盘中,一般钝化发生在服务器停止,服务器停止时会自动将HttpSession对象序列化到硬盘,这个事我们称为钝化。

  • 活化

将硬盘中HttpSession对象加载进内存中,一般在服务器启动时,会自动将硬盘中HttpSession对象重新加载进内存,这一过程我们成为活化。

  • 钝化指将内存中的对象写到硬盘中,

  • 一个类要想可以序列化到硬盘中必须要实现java.io.Serializable接口

  • 这个类中的所有属性也需要实现java.io.Serializable接口

  • 如果服务器的访问量较大,那么服务器会有大量的HttpSession对象存在,

但是这些对象并不是都处于一个活跃的状态,但是这些不活跃也会存在于内存中

这样会大量占用内存,这时我们就希望将这些闲置的对象写入硬盘中,

在用户需要使用session在加载进内存。

在context.xml文件中可以加入如下内容

maxIdleSwap:指session的最大闲置时间,超过该时间以后,session将会自动钝化。

directory:钝化到硬盘中的目录

session会钝化到tomcat服务器的work目录中

表单的重复提交

  • 表单重复提交指的是同一个表单相同的内容多次提交请求

  • 表单重复提交的危害:

1.表单重复提交,都是重复的数据,会增加数据库中垃圾数据。

2.无形中增加了服务器压力。

  • 表单重复提交的几种情况:

1.表单提交成功以后,反复刷新成功页面。

  • 产生问题的根本原因:

我们在Servlet使用的转发的形式跳转到成功页面的,所以整个过程中浏览器只发送了一次请求,当我们在成功页面刷新时,实际是将上次的请求又发送了一遍,所以造成了重复提交。

  • 解决:

不使用转发,而是使用重定向

重定向发了两次请求,我们再次刷新,刷新的第二个请求,而不是第一个。

2.网速较慢时,用户多次点击提交按钮。

  • 产生问题的根本原因:

就是表单的提交按钮可以点击多次

  • 解决:

使表单的提交按钮只能点一次,点完一次以后按钮将变为不可用的状态。

window.onload = function(){

//点击完提交按钮以后,让按钮变为一个不可用的状态

//获取按钮对象

var btn = document.getElementById(“btn”);

//为按钮绑定一个单击响应函数

btn.onclick = function(){

//设置按钮为不可用状态

this.disabled = true;

//如果将按钮设置为不用状态,那么表单也将不会提交

//我们需要手动提交表单

this.parentNode.submit();

};
};

3.成功提交请求后,点击回退按钮,但是不刷新页面,再次提交。

  • 产生问题的根本原因:

服务器端的Servlet不能区分两次请求是不是重复提交的内容

  • 解决:

在Servlet中,我们需要在处理请求之前,先来检查表单是否是重复提交。

使用token解决这个问题

token就是令牌意思

所谓的token就是服务器在处理用户请求之前,先检查token是否正确,如果token正确那服务器正常处理请求,如果token不正确服务器不处理请求.

我们的令牌是一个一次性的令牌,只能使用一次.

流程:

1.创建一个令牌,要求唯一,不能重复(UUID),并在服务器中保存token。

2.放入到浏览器的表单中。

3.浏览器提交表单时,会同时将token一起提交。

4.服务器在处理请求之前要检查令牌是否有效。

5.销毁token。

验证码使用流程:

验证码(kaptcha)


kaptcha

上述工作,大部分工作我们都可以通过一款jar包来完成。
kaptcha-2.3.2
该Jar可以:
1.可以生成一个随机的字符串
2.可以将字符串保存到session
3.可以将字符串转换为一个图片
这个kaptcha-2.3.2里边实际上就是一个Servlet,我们通过访问他给我们提供的Servlet,就可以直接完成上述工作

导入jar包之后,通过在web.xml文件中注册servelt即可。

< servlet>    < servlet-name >kaptcha</ servlet-name>    <servlet-class> com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class >    <init-param >       //在session中存储该验证码的属性的名字      <param-name> kaptcha.session.key</param-name >      <param-value >code</ param-value>    </init-param >  </servlet >  <servlet-mapping >    <servlet-name >kaptcha</ servlet-name>    <url-pattern >/code.jpg</ url-pattern>  </servlet-mapping >

kaptcha-2.3.2常用的配置信息(属性键值对)
(< param-name>和< param-value>的内容)

kaptcha.border验证码图片的边框,可以设置yes或者no默认值 yeskaptcha.border.color边框的颜色reg值。合法值 rgb,black,blue,white默认值 blackkaptcha.border.thickness边框的宽度默认 1kaptcha.image.width图片的宽度默认200kaptcha.image.height图片的告诉默认50kaptcha.producer.impl生成图片使用的类默认 com.google.code.kaptcha.impl.DefaultKaptchakaptcha.textproducer.impl生成图片中文字的使用的类默认com.google.code.kaptcha.text.impl.DefaultTextCreatorkaptcha.textproducer.char.string验证码中使用的字符默认 abcde2345678gfynmnpwxkaptcha.textproducer.char.length验证码中字符的数量默认 5kaptcha.textproducer.font.names验证码的字体默认 Arial, Courierkaptcha.textproducer.font.size字体的大小默认 40kaptcha.textproducer.font.color字体颜色 rgb值,颜色单词默认 blackkaptcha.textproducer.char.space两个字符之间的间距默认 2kaptcha.noise.impl干扰线生成类默认 com.google.code.kaptcha.impl.DefaultNoisekaptcha.noise.color干扰线颜色默认 blackkaptcha.obscurificator.implThe obscurificator implementation.默认 com.google.code.kaptcha.impl.WaterRipplekaptcha.background.impl背景颜色设置类默认 com.google.code.kaptcha.impl.DefaultBackgroundkaptcha.background.clear.from渐变颜色 左到右默认 light greykaptcha.background.clear.to渐变颜色 右到左默认 whitekaptcha.word.impl词语渲染器默认 com.google.code.kaptcha.text.impl.DefaultWordRendererkaptcha.session.key在session中存储属性的名字默认 KAPTCHA_SESSION_KEY<script type="text/javascript">    $(function(){        $('#kaptchaImage').click(function () {        $(this).attr('src', '/kaptcha.jpg?' + Math.floor(Math.random()*100) ); })    });</script>
0 0