会话

6 篇文章 0 订阅
1 篇文章 0 订阅

1. 会话技术

1.1. 会话技术

1.1.1. 会话概述

会话可简单理解为:用户开一个浏览器,访问多个资源,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。

1.1.2. 会话中的问题

每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。

如用户登录过后,应该保存一个用户状态,在会话结束前表明用户一直是登录状态。并且不同的用户之间的登录状态应该互不影响。

我们之前已经学过request域和SerlvetContext域,我们分别分析一下。

Request域太小了,在多次请求中,每次请求响应都是新的Request对象,之前存入的request域中的域属性,在请求结束后随着request域的销毁而消失了。

ServletContext域太大了,所有用户都在操作这个域,必然会发生混乱。

此时我们需要会话相关的技术,保存会话产生的数据。

2. Session技术

2.1. Session技术

2.1.1. Session概述

Session的原理

Session是基于一个JSESSIOINIDCookie工作的

 

Ø 怎么解决浏览器关闭之后, 无法使用浏览器关闭之前的Session??

(注意: 在访问一个jsp, 默认一上来就会创建session!!)

 

Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

如图-1所示:

 

-1

2.1.2. session是一个域对象

生命周期:

当程序第一次调用到request.getSession()代码时,服务器明确的直到了需要用到session,此时创建session.

如果session超过30分钟(可以在web.xml中配置的)没人使用,服务器认为这个session超时了,销毁session.

明确的调用session.invalidate(),session立即销毁.

服务器被非正常关闭或web应用被移除出容器,此时随着web应用的销毁session销毁.如果是正常关闭,session会被钝化.当下次服务器正常启动时,没有超时的session还会被活化回来.

作用范围:

整个会话范围内可见

主要作用:

在会话范围内共享数据

2.2. 利用Session实现EasyMall中的登录功能

2.2.1. 登录的原理

所谓的登录,就是要将登录过后的用户状态保存起来,在后续的请求中能够获知这种状态,这就是典型的在会话中保存数据的过程。

我们可以在Session中保存一个登录标记,表明当前用户已经登录过。后续需要时只需检查Session中的该标记即可判断出用户是否登录过。

2.2.2. 登录代码实现

首先我们导入用户登录页面,如图-2所示:

 

-2

创建登录用的Servlet,将登录用表单的地址设置为该Servlet,如图-3所示:

 

-3

Servlet我们获取用户提交的用户名密码

//解决请求乱码

request.setCharacterEncoding("utf-8");

//解决响应乱码

response.setContentType("text/html;charset=utf-8");

 

//获取用户提交的用户名 密码

String username = request.getParameter("username");

String password = request.getParameter("password");

通过查询数据库检查用户名密码是否正确,如果不正确则进行提示,如果正确则在Session中保存用户的登录状态后回到主页

//查询数据库是否存在指定用户名密码的用户

try {

SAXReader reader = new SAXReader();

Document dom = reader.read(this.getServletContext().getRealPath("WEB-INF/classes/users.xml"));

Element root = dom.getRootElement();

Element ele = (Element) root.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']");

if(ele == null){

//没有找到,提示用户名密码不正确

response.getWriter().write("用户名密码不正确!");

return;

}else{

//用户名密码正确,将用户名保存到session中表明用户登录过

request.getSession().setAttribute("user", username);

//回到主页

response.sendRedirect("/index.jsp");

}

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

}

2.3. Session实现防止表单重复提交

2.3.1. 表单重复提交概述

当网络延迟等情况发生时,用户无法确定表单是否已经提交,从而多次点击提交,造成数据多次提交,称为发生了表单重复提交。

真实案例:12306网站购票

2.3.2. 防止表单重复提交

生成一个令牌。

session域中保存令牌。

在表单中隐藏字段保存令牌。

当表单提交时,在处理的Servlet里检查,如果提交的令牌和session中保存的令牌一致,则执行逻辑,并删除session中的令牌。

如果session域中没有令牌,或和提交的令牌不符合,则认为是表单重复提交,提示。

2.3.3. EasyMall注册用户防止表单重复提交

regist.jsp中设置代码保存令牌我们此处用随机数作为令牌。如图-4所示:

 

-4

RegistServlet中检查,如图-5所示:

 

-5

2.4. Session实现验证码

验证码提交后该如何进行校验呢?应该在用户获取验证码时,将验证码信息存入session域,在用户提交表单时,将用户提交的验证码和session中保存的验证码进行比较,如果一致,则验证码正确。

ValiImgServlet,如图-6所示:

 

-6

RegistServlet,如图-7所示:

 

-7

regist.jsp,如图-8所示:

 

-8

3. Cookie技术

3.1. Cookie技术

3.1.1. Cookie概述

Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。如图-9所示:

 

-9

cookie是会话相关的技术,可以保存会话产生的数据,客户端技术,将数据保存在客户端,基于set-Cookie响应头和Cookie请求头工作的.

3.1.2. Cookie常用方法

Cookie cookie = new Cookie(String name,String value);

--javax.servlet.http.Cookie类用于创建一个Cookie

 

setValuegetValue方法

--设置和获取cookie的值


getName方法

--cookie需要在创建时就指定好名字,这个名字一旦指定就不能修改了,如果需要修改只能重新创建一个cookie

 

setMaxAgegetMaxAge方法  

--一个cookie被发送到浏览器时,如果没有设置过MaxAge,这个cookie将会被保存在浏览器的内存中,会一直存在到浏览器关闭内存销毁为止,这样的cookie叫做会话级别的Cookie

--我们也可以使用setMaxAge方法设置cookie的存活时间,这样一来,浏览器收到这个Cookie信息时会将cookie信息以文件的形式保存在浏览器的临时文件夹中,保存到指定的时间到来位置,在这个期间即使多次开关浏览器,cookie信息一直都在.

 

setPathgetPath方法

--设置浏览器在访问哪个地址及其子地址时,带着cookie信息过来.如果没设置过,那么默认的path是当前发送cookieServlet所在的路径

 

setDomaingetDomain方法 (了解)

--设置浏览器在访问哪个域名时,带着当前的cookie,默认值当前发送cookie的域名,注意,现代的浏览器只要发现cookie设置过maxage,则认为这个cookie是第三方cookie,会拒绝接受

 

 

3.1.3. 发送cookie

response.addCookie(cookie);

--response接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。

3.1.4. 获取cookie

request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie

Cookie [] cs = request.getCookies();

3.1.5. 删除cookie

浏览器会通过名字+path+domaint来区分cookie,如果浏览器发现两个cookie名字 path domain 都相同,则会认为是相同的cookie,就会发送cookie的覆盖。

所以如果想要删除一个cookie,可以发送一个和要删除的cookie名字 path (domain) 都相同的cookie,然后将这个cookiemaxAge设置为0,这样一来,这个cookie会把要删除的cookie覆盖掉,覆盖后立即超时,直接被浏览器删除,看起来就像是删除了要删除的cookie

3.1.6. Cookie细节

一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。

一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie

浏览器一般只允许存放300Cookie,每个站点最多存放20Cookie,每个Cookie的大小限制为4KB

如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie

注意,删除cookie时,path必须一致,否则不会删除(浏览器通过cookiename+path来标识一个cookie)

3.2. EasyMall实现记住用户名功能

3.2.1. 记住用户名功能分析

登录页面如图-10所示:

 

-10

如果用户在登录时勾选了记住用户名,则应该将用户名称用户名保存起来,在用户下次登录时,读取保存的用户名,显示出来。

如果用Session保存,我们知道,Session一旦30分钟不使用就会失效,这个时间显然太短了。

而用Cookie保存,可以设置MaxAge指定保存的时常,直到指定时间结束或用户手动清楚cookie之前,此信息一直存在。

所以我们选择Cookie来实现保存用户名的功能。

3.2.2. 代码实现

在用户登录的Servlet中,当用户登录成功后,判断用户是否勾选过记住用户名,如果用户勾选过,则发送cookie保存用户名,注意MaxAge设置为30天。

//查询数据库是否存在指定用户名密码的用户

try {

SAXReader reader = new SAXReader();

Document dom = reader.read(this.getServletContext().getRealPath("WEB-INF/classes/users.xml"));

Element root = dom.getRootElement();

Element ele = (Element) root.selectSingleNode(

"//user[@username='"+username+"' and @password='"+password+"']"

);

if(ele == null){

//没有找到,提示用户名密码不正确

response.getWriter().write("用户名密码不正确!");

return;

}else{

//用户名密码正确,将用户名保存到session中表明用户登录过

request.getSession().setAttribute("user", username);

//检查用户是否勾选过记住用户名

if("true".equals(request.getParameter("remname"))){

//发送cookie保存用户名

Cookie remnamec = new Cookie("remname",username);

remnamec.setPath("/");

remnamec.setMaxAge(3600*24*30);

response.addCookie(remnamec);

}

//回到主页

response.sendRedirect("/index.jsp");

}

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

}

经过测试,发现当用户勾选过记住用户名时,会发送cookie给浏览器保存用户名。如图-11所示:

 

-11

当浏览器再次访问登录页面时,请求中带了cookie,其中保存着用户名。如图-12所示:

 

-12

现在我们只需要在登录页面,读取到cookie中保存的用户名显示到用户名输入项即可。

我们当前输出登录页面用的是html页面,html是静态web资源无法在其中写代码读取cookie数据,所以我们改造为用jsp实现。

login.html改为login.jsp,在其中嵌入java代码,读取请求中的cookie信息,填入用户名输入框。如图-13所示:

 

-13

经测试,可以正确的显示用户名,如图-14所示:

 

-14

上面的测试中我们用的用户名是英文的,再测试一下中文。如图-15所示:

 

-15

提交后发现报错,如图-16所示:

 

-16

为什么会报错呢?我们知道cookie是基于HTTP协议中的set-Cookie请求头和Cookie响应头工作的。而HTTP协议本身只支持ISO8859-1编码,ISO8859-1中没有中文,所以报错了。

那么该如何解决呢?

Web开发中有一种常用的编码方式叫URL编码就是用来解决这种问题的。

4. URL编码

4.1. URL编码

4.1.1. URL编码概述

其实这种编码方式我们见过,当我们用浏览器提交中文数据时,中文数据也是经过URL编码后提交的。对于非iso8859-1的字符,浏览器和服务器默认使用URL编码进行处理。如图-16所示:

 

-16

4.1.2. URL编码原理

4.1.3. URL编解码

Java中提供了进行URL编码和解码的类

URLEncoderstatic String encode(String s,String enc);

//将指定的字符串按照指定的编码转换为URL编码的形式

URLDecoderstatic String decode(String s,String enc);

//URL编码后的字符串按照指定编码解码为源字符串

4.2. EasyMall记住用户名中文处理

4.2.1. EasyMall记住用户名中文处理

我们可以通过URL编码解决集中用户名中的中文问题。

改造代码,在发送cookie时,进行URL编码

//检查用户是否勾选过记住用户名

if("true".equals(request.getParameter("remname"))){

//发送cookie保存用户名

Cookie remnamec =

new Cookie("remname",URLEncoder.encode(username, "utf-8"));

remnamec.setPath("/");

remnamec.setMaxAge(3600*24*30);

response.addCookie(remnamec);

}

经测试cookie中保存的是进过URL编码的用户名。如图-17所示:

 

-17

login.jsp中,用户名要经过URL解码,如图-18所示:

 

-18

经测试,可以正常的处理中文用户名。如图-19所示:

 

-19

5. session的原理

5.1. Session原理

5.1.1. Session原理

服务器是如何区别出当前请求是要对应到哪个Sessoin的呢?其实Session是基于一个特殊的名为JSESSIONIDcookie工作的。如图-20所示:


-20

5.2. 利用Session原理实现即使多浏览器共用Session

5.2.1. 代码实现

利用sesison的原理,我们可以自己写出一个JSESSIONID cookie,设置maxAge,从而实现即使关闭浏览器仍能找到之前的session

 

-21

5.3. 禁用cookie时使用session

5.3.1. 禁用cookie时使用session

当客户端禁用了cookie,造成session无法访问,此时我们可以使用URL重写来解决这个问题

URL重写要求将站点中的所有超链接都进行改造,在超链接后用一个特殊的参数JSESSIONID保存当前浏览器对应session的编号,这样一来,当用户点击超链接访问服务器时,服务器可以从URL后的参数中分析出JSESSIONID,从而找到对应的sesison使用.

URL重写之前,要先创建出session,才能进行重写操作

response.encodeURL(String url);

//--如果是普通的地址用这个方法

response.encodeRedirectURL(String url);

//--如果地址是用来进行重定向的,用这个方法

以上两个方法可以实现URL重写,这两个方法非常的智能,只要发现浏览器发送了任何Cookie过来,就认为当前客户端没有禁用Cookie,就不会在进行URL重写

CookieSession的比较

(1) Cookie是将会话中产生的数据保存在客户端, 是客户端的技术

(2) Session是将会话中产生的数据保存在服务器端, 是服务器端的技术

(3) Cookie保存的信息的时间比较长, 但是安全性不高. 可能随着用户的操作, Cookie会被清空, 所以Cookie存储数据的稳定性比较差. 因此Cookie适合存放要保存时间较长, 但安全性要求不高的信息

(4) Session通常保存信息的时间比较有限, 但安全性比较高, 因为是保存在服务器端, 不会随着用户的操作而导致Session意外丢失, 因此session适合存放安全性要求比较高, 但是不需要长时间保存的数据.

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值