您的位置:首页 > 其它

会话管理之Session

2016-07-18 21:55 176 查看
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)



上述工作,大部分工作我们都可以通过一款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
默认值 yes

kaptcha.border.color
边框的颜色reg值。合法值 rgb,black,blue,white
默认值 black

kaptcha.border.thickness
边框的宽度
默认 1

kaptcha.image.width
图片的宽度
默认200

kaptcha.image.height
图片的告诉
默认50

kaptcha.producer.impl
生成图片使用的类
默认 com.google.code.kaptcha.impl.DefaultKaptcha

kaptcha.textproducer.impl
生成图片中文字的使用的类
默认com.google.code.kaptcha.text.impl.DefaultTextCreator

kaptcha.textproducer.char.string
验证码中使用的字符
默认 abcde2345678gfynmnpwx

kaptcha.textproducer.char.length
验证码中字符的数量
默认 5

kaptcha.textproducer.font.names
验证码的字体
默认 Arial, Courier

kaptcha.textproducer.font.size
字体的大小
默认 40

kaptcha.textproducer.font.color
字体颜色 rgb值,颜色单词
默认 black

kaptcha.textproducer.char.space
两个字符之间的间距
默认 2

kaptcha.noise.impl
干扰线生成类
默认 com.google.code.kaptcha.impl.DefaultNoise

kaptcha.noise.color
干扰线颜色
默认 black

kaptcha.obscurificator.impl
The obscurificator implementation.
默认 com.google.code.kaptcha.impl.WaterRipple

kaptcha.background.impl
背景颜色设置类
默认 com.google.code.kaptcha.impl.DefaultBackground

kaptcha.background.clear.from
渐变颜色 左到右
默认 light grey

kaptcha.background.clear.to
渐变颜色 右到左
默认 white

kaptcha.word.impl
词语渲染器
默认 com.google.code.kaptcha.text.impl.DefaultWordRenderer

kaptcha.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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: