一、会话控制
1.为什么会出现会话控制
HTTP协议的特点:
纯文本但是有时候我们需要让浏览器知道多个请求来自同一个用户,比如:网上购物。所以就出现了会话控制
无状态
浏览器不能区分多个请求是否来自同一个用户
会话控制涉及到两种技术
Cookie
Session
2.Cookie
Cookie就是服务器发送给浏览器的用于区分不同用户的一段信息Cookie的运行机制
1)服务器创建一个Cookie对象
2)服务器将Cookie对象发送给浏览器
3)以后浏览器发请求就会携带着该Cookie对象
4)服务器根据Cookie对象来区分不同的用户
创建Cookie对象
//1.创建Cookie,Cookie对象的名称(key)不能使用中文
Cookie cookie = new Cookie("username", "sunwukong");
Cookie cookie2 = new Cookie("username2", "zhubajie");
//2.将Cookie对象发送给浏览器
response.addCookie(cookie);
response.addCookie(cookie2);
获取Cookie对象
//1.获取Cookie对象
Cookie[] cookies = request.getCookies();
//2.遍历得到每一个Cookie对象
if(cookies != null){
for (Cookie cookie : cookies) {
//获取Cookie对象的名称
String name = cookie.getName();
System.out.println(name);
//获取Cookie对象的值
String value = cookie.getValue();
System.out.println(value);
}
}
修改Cookie对象
//修改Cookie对象有以下两种方式:
//方式一:创建一个同名的Cookie对象
//Cookie cookie = new Cookie("username", "meihouwang");
//response.addCookie(cookie);
//方式二:修改Cookie的value值
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
String name = cookie.getName();
if("username".equals(name)){
cookie.setValue("qitiandasheng");
//将修改之后的Cookie对象发送给浏览器
response.addCookie(cookie);
}
}
}
持久化Cookie对象
//创建一个Cookie对象
Cookie cookie = new Cookie("user", "admin");
//持久化Cookie对象
/*
* 通过setMaxAge(int age)方法来持久化Cookie对象
* age > 0 :在age秒后Cookie对象失效
* age = 0 :Cookie对象立即失效
* age < 0 :会话级别的Cookie对象,默认
*/
//设置Cookie对象7天内有效
//cookie.setMaxAge(60*60*24*7);
cookie.setMaxAge(-9);
//将Cookie对象发送给浏览器
response.addCookie(cookie);
Cookie对象的有效路径:
不是访问任何路径都会携带所有的Cookie对象
Cookie的有效路径即访问那些路径时会携带该对象,默认的有效路径是当前Web应用的根目录,我们还可以通过setPath()方法设置Cookie对象的有效路径
//创建一个Cookie对象
Cookie cookie = new Cookie("user2", "admin2");
//设置Cookie对象的有效路径
//setPath()中的路径由浏览器解析
cookie.setPath("/Web07_Cookie/hello");
response.addCookie(cookie);
Cookie对象的用途:
广告推送
免登录
Cookie的缺陷:
Cookie对象是明文的,不安全所以就出现了Session
不同的浏览器对Cookie对象的大小和个数有限制
Cookie对象过多耗费流量
3.Session
Session即我们非常熟悉的HttpSession,用来保存用户信息Session的运行机制
1)在服务器端创建一个Session对象,该对象有一个全球唯一的ID
2)在服务器端创建Session对象的同时还会创建一个name为一个固定值JSESSIONID的Cookie对象并发送给浏览器,而且这个特殊的Cookie对象的value值就是Session对象的ID
3)以后浏览器发送请求时会携带name为JSESSIONID的Cookie对象,服务器会根据Cookie对象的value值来验证是否有对应的Session对象
4)服务器根据name为JSESSIONID的Cookie对象来区分不同的用户
Session对象的创建
Session对象在Servlet中通过request获取,只有获取了Session对象才会设置对应的name为JSESSIONID的Cookie对象
//获取Session对象
HttpSession session = request.getSession();
//获取session对象的id
String id = session.getId();
System.out.println(id);
通过持久化JSESSIONID的Cookie对象来保持Session对象
当我们关闭浏览器时,由于Cookie默认是会话级别的,所以JSESSIONID对应的Cookie对象失效,再次打开浏览器时就不能找到之前创建的Session对象,我们可以通过将JSESSIONID的Cookie对象持久化的方法找到之前的Session对象
//获取ookie对象
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
//获取cookie的name
String name = cookie.getName();
if("JSESSIONID".equals(name)){
//持久化该Cookie对象
cookie.setMaxAge(60);
//发送给浏览器
response.addCookie(cookie);
}
}
}
设置Session对象的最大空闲时间
Session对象的默认最大空闲时间是30分钟,我们还可以设置它的最大空闲时间
//获取Session对象
HttpSession session = request.getSession();
//设置Session对象的最大空闲时间
/*
* 可以通过setMaxInactiveInterval(int age)来设置Session对象的最大空闲时间
* age > 0 : 在age秒后Session对象失效
* age = 0 : Session对象立即失效
* age < 0 : Session对象永远不失效
*
*/
session.setMaxInactiveInterval(-8);
//我们通常使用下面的方法设置Session对象立即失效
session.invalidate();
钝化与活化:
钝化:Session对象及session域中的属性从内存中序列化到硬盘上的过程
活化:Session对象及session域中的属性从硬盘上反序列化到内存中的过程
要保证Session域中的属性可以被钝化和活化Session域中的属性必须实现Serializable接口
URL重写
在浏览器禁用Cookie的情况下,每次发请求无法携带Cookie对象,就导致无法找到之前创建的Session对象,这种情况下就可以通过URL重写将JSESSIONID通过参数的形式发送到服务器,从而找到对应的Session对象
URL重写有以下方式
<%
//通过response的两个方法
String url = response.encodeURL(request.getContextPath()+"/login.jsp");
String url2 = response.encodeRedirectURL(request.getContextPath()+"/login.jsp");
%>
<!-- 通过标签 -->
<c:url value="/login.jsp"></c:url>
二、表单的重复提交
同一个表单,同样的内容向服务器提交多次表单重复提交的危害:
增加服务器的压力
数据库中会保存很多垃圾数据
表单重复提交主要有以下三种情况:
1)在转发的情况下:表单提交成功之后反复刷新成功页面
产生的原因:在转发的情况下,地址栏没有变化,刷新成功页面相当于重复向form表单中的action属性值重复提交请求解决方案:使用重定向
2)在网速很慢的情况下:反复点击提交按钮
产生的原因:提交按钮可以被点击多次解决方案:让提交按钮只能点击一次
3)表单提交成功之后,点击返回(回退)按钮,在不刷新页面的情况下再一次提交表单
产生的原因:服务器会处理重复提交的请求解决方案:使用token(记号)来判断是否是重复提交的请求
使用token的流程
①在服务器端使用UUID生成一个全球唯一的字符串(token),然后将它放到session域中
②将全球唯一的token放到表单的隐藏域中,随着表单一起提交到服务器
③在服务器端获取表单隐藏域中的token,然后session域中的token进行对比,如果相等:正常处理请求,不相等:即为重复提交请求。
④将session域中的token移除