Java web-Cookie与Session

1.会话技术

1.1.概述

客户端为了实现某一功能,发生了多次的请求响应,从客户端开始访问服务器开始,到访问结束,这期间产生的多次请求响应加在一起称之为一个会话。

1.2.会话中的问题

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

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

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

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

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

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


Cookie
cookie的原理是利用Set-cookie响应头和cookie请求头
cookie将会话产生的数据保存在了客户端中,是客户端技术。
Session

session将会话产生的数据保存在了服务器端,是服务器端的技术

1.3.Cookie

1.3.1.概述

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

Java web-Cookie与Session_第1张图片

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

1.3.2.Cookie常用方法

Cookie cookie = new Cookie(String name,String value);
--javax.servlet.http.Cookie类用于创建一个Cookie
setValue与getValue方法
--设置和获取cookie的值
	getName方法
--cookie需要在创建时就指定好名字,这个名字一旦指定就不能修改了,如果需要修改只能重新创建一个cookie
setMaxAge与getMaxAge方法  
--一个cookie被发送到浏览器时,如果没有设置过MaxAge,这个cookie将会被保存在浏览器的内存中,会一直存在到浏览器关闭内存销毁为止,这样的cookie叫做会话级别的Cookie
--我们也可以使用setMaxAge方法设置cookie的存活时间,这样一来,浏览器收到这个Cookie信息时会将cookie信息以文件的形式保存在浏览器的临时文件夹中,保存到指定的时间到来位置,在这个期间即使多次开关浏览器,cookie信息一直都在.
 
setPath与getPath方法
--设置浏览器在访问哪个地址及其子地址时,带着cookie信息过来.如果没设置过,那么默认的path是当前发送cookie的Servlet所在的路径
 
setDomain与getDomain方法 
--设置浏览器在访问哪个域名时,带着当前的cookie,默认值当前发送cookie的域名,注意,现代的浏览器只要发现cookie设置过maxage,则认为这个cookie是第三方cookie,会拒绝接受

1.3.3.发送cookie

response.addCookie(Cookie c);//向响应中增加一个cookie,可以在一次响应中增加多个cookie


1.3.4.获取cookie

Cookie [] cs = request.getCookies();//返回请求中所有cookike信息组成的数组,如果请求中没有任何cookie信息此方法返回null


1.3.5.删除cookie

        浏览器是通过 名字+path+domain来区分cookie,如果发现cookie具有了相同的名字、path和domain时,cookie会发生覆盖。

        所以如果想要删除一个cookie,只要发送一个同名 同path 的cookie,但是maxAge设置为0,覆盖掉要删除的cookie,覆盖过后,新的cookie立即超时,被浏览器删除,感觉起来就好像旧的cookie被删除了一样。


1.3.6.cookie细节

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

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

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

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

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


案例:实现记住用户名功能

功能分析

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

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

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

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

代码实现

在用户登录的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);
}


1.4.Session

1.4.1.概述

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

Java web-Cookie与Session_第2张图片


1.4.2.Session是一个域对象

生命周期:

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

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

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

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

作用范围:

整个会话范围内可见

主要作用:

在会话范围内共享数据

1.4.3.实现登录功能

1.4.3.1.登录原理

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

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

1.4.3.2.代码实现

在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);
}

1.4.4.实现防止表单重复提交

1.4.4.1.表单重复提交概述

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

真实案例:12306网站购票

1.4.4.2.防止表单重复提交

生成一个令牌。

在session域中保存令牌。

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

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

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

1.4.4.3.代码实现

jsp中代码

Java web-Cookie与Session_第3张图片

java中代码

Java web-Cookie与Session_第4张图片

1.4.5.实现验证码

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

ValiImgServlet,如图:

Java web-Cookie与Session_第5张图片

RegistServlet,如图:

Java web-Cookie与Session_第6张图片

regist.jsp,如图:

Java web-Cookie与Session_第7张图片


cookie和session比较:

cookie是客户端的技术,会话产生的数据保存在客户端。session是服务器端的技术,会话产生的数据保存在服务器端。
cookie信息可以保存的时间比较长。但是安全性不高。可能随着用户的操作cookie会被清空,数据稳定性比较差。所以cookie适合存放要保存的时间比较长,安全性要求不高,丢失也无所谓的信息。
session信息保存的时间通常比较有限。但是安全性高,并且在session存活期间,数据一直存在稳定性很高,不会因为用户的操作导致session中数据以外丢失。所以session适合存放数据安全性稳定性要求比较高,但是不需要长时间保存的数据。

1.5.URL编码

1.5.1.概述

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

浏览器和服务器之间是通过HTTP协议通信的
HTTP协议只支持ISO8859-1字符集 
所以其实从理论上来说 HTTP协议只能处理 ISO8859-1中具有的字符 不能处理中文
怎么解决HTTP协议携带中文的问题呢? -- URL编码
通过URL编码 客户端将非iso8859-1的字符转换为 URL编码形式 发送给服务器 服务器收到后再进行URL解码 就可以转换回原来的字符了

1.5.2.URL编解码

Java中提供了进行URL编码和解码的类
URLEncoder:static String encode(String s,String enc);
//将指定的字符串按照指定的编码转换为URL编码的形式
URLDecoder:static String decode(String s,String enc);
//将URL编码后的字符串按照指定编码解码为源字符串

案例:对cookie进行中文处理

改造代码,在发送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);
}

jsp中,用户名要经过URL解码

Java web-Cookie与Session_第8张图片

Java web-Cookie与Session_第9张图片


你可能感兴趣的:(Java,web)