会话技术概述
会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。
从用户通过浏览器第一次给服务器资源发送请求,此时会话建立,直到有一方断开为止;整个会话过程包含该用户的多次请求和响应过程;
由于Web应用程序是使用HTTP协议传输数据的,而HTTP协议是无状态的协议,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接,这就意味着服务器无法从连接上跟踪会话,要跟踪用户的会话,必须引入一种机制。
常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
总结:
由于http协议无状态,在每一次请求和响应结束后,服务器不会知道再次请求的还是你,所以引入会话技术就是实现在一次会话中的多次请求响应之间共享数据。
常用的会话技术是Cookie与Session。
Cookie通过在客户端记录信息确定用户身份
Session通过在服务器端记录信息确定用户身份。
参考文章:
https://www.cnblogs.com/l199616j/p/11195667.html#_label0_8
Cookie
1.Cookie的创建
@WebServlet("/CookieDemo01")
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建Cookie
Cookie c1 = new Cookie("msg", "hello");
Cookie c2 = new Cookie("username", "zxf");
//发送Cookie
response.addCookie(c1);
response.addCookie(c2);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
注:一个Cookie只能存储一个k-v
@WebServlet("/CookieDemo02")
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取Cookie
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name+":"+value);
}
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
2.Cookie原理
- 客户端浏览器第一次发送请求,将用户信息携带给请求的服务器资源;
- 服务器做出响应的时候,将信息添加到Cookie中,由响应头中set-cookie属性携带给客户端浏览器
- 客户端以后再次发送请求的时候,会将Cookie数据 放在请求头Cookie属性中携带给服务器
图示:
第一次请求Demo01添加Cookie:
第二次请求Demo02:
所以Cookie原理就是:
基于响应头set-cookie和请求头Cookie实现
Cookie保存时间
默认情况下,Cookie保存到浏览器关闭;也就是说一直存储在内存中,浏览器关闭Cookie被销毁。
api:
setMaxAge(int seconds)
1.正数 将Cookie数据持久化到硬盘 ,cookie存活时间
2.负数 默认情况
3.零 删除Cookie信息(清空指定的本地Cookie数据)
Cookie c2 = new Cookie("username", "zxf");
c2.setMaxAge(0);
Cookie存储中文数据
Tomcat8之前,Cookie不支持存储中文数据
Tomcat8之后,支持存储中文数据;但是仍然不支持特殊字符,建议使用url编码解码
URLEncoder.encode(String str,String charset)
URLDecoder.decode(String str,String charset)
Cookie获取范围
默认情况下,Cookie仅限于同一个Web项目;如果是一个Tomcat服务器中部署了多个Web项目,在这些web项目之间Cookie是不能共享的
(1) 同一个服务器容器中,不同的web项目之间共享设置
setPath(String path) :默认情况下,path为当前的项目的虚拟目录
如果要设置为Tomcat服务器内多个项目之间共享,将路径设置为Tomcat根目录 即 “/”
Cookie c1 = new Cookie("msg", "hello");
c1.setPath("/Cookie_Session");//当前项目的虚拟目录
(2)跨服务器共享设置
setDomain(String path):如果设置一级域名相同,那么多个服务器之间的cookie可以共享
Cookie c = new Cookie("username","user");
c.setDomain(".baidu.com");
如上设置,那么 tieba.baidu.com或者news.baidu.com中cookie可以共享
Cookie特点及使用场景
特点:
1.cookie数据存储在客户端浏览器 不安全,容易被修改
2.浏览器对于单个Cookie的大小有限制(4kb)
3.同一个域名下的Cookie数也有限制(20个)
使用场景
1.cookie一般用于存储少量不敏感数据
2.在不登陆情况下,完成服务器对客户端身份识别
Cookie案例
@WebServlet("/CookieTest")
public class CookieTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = sdf.format(date);
String nowEncode = URLEncoder.encode(now, "utf-8");
boolean flag = false;
Cookie[] cookies = request.getCookies();
if(cookies != null || cookies.length > 0){
for (Cookie cookie : cookies) {
String name = cookie.getName();
if(name.equals("lastTime")){
flag = true;
String lastTime = cookie.getValue();
String decode = URLDecoder.decode(lastTime, "utf-8");
writer.write("欢迎回来,您上次的访问时间为"+ decode);
cookie.setValue(nowEncode);
break;
}
}
}
if(flag == false){
Cookie lastTime = new Cookie("lastTime", nowEncode);
response.addCookie(lastTime);
writer.write("您好,这是您首次登陆");
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
Session
1.Session的使用
HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name,Object value)
void removeAttribute(String name)
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/SessionDemo01")
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取Session
HttpSession session = request.getSession();
session.setAttribute("username","demo01");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/SessionDemo02")
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取Session
HttpSession session = request.getSession();
Object username = session.getAttribute("username");
System.out.println(username);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
2. Session原理
服务器如何确保在一次会话范围内,多次获取Session对象是同一个?
1.Session是基于Cookie的
2.第一次获取Session的时候,是没有响应的Cookie,会在内存中创建一个新的Session对象,该对象有唯一ID标识
3.在响应的时候,会在响应头中添加一个set-cookie头:JSESSIONID= SessionID
4.以后浏览器再次发送请求的时候,会携带Cookie头,此时服务器再getSession()的时候器会根据JSESSIONID属性的值,在服务器内存中找对应的SessionID,找到了就获取此对象!
抓包演示:
3.Session生命周期
1.关闭浏览器,不关闭服务器
默认情况下,关闭客户端浏览器后,服务器不关闭,两次获取的Session不会是同一个,因为Cookie头没了。如果想修改Session生命周期,手动设置.
HttpSession session = request.getSession();
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60*60);
2.关闭服务器
当服务器关闭的时候,由于Tomcat也会关闭,释放内存,因此Session对象也会销毁!
Session钝化:
服务器正常关闭之前,会将Session对象序列化到硬盘上
Session活化:
服务器启动之后,会将Session文件反序列化为内存中的session对象
3.Session的失效时间
1.服务器关闭
2.session对象调用invalidate()
3.页面没有任何活动 默认失效时间30min
在web.xml文件中有配置:
<session-config>
<session-timeout>30</session-timeout>
</session-config>
4.Session特点与应用场景
1.用于存储一次会话的多次请求的数据,存在于服务器端
2.session可以存储任意类型,任意大小的数据
session与Cookie的区别:
1.session存储数据在服务器端,Cookie在客户端
2.session没有数据大小限制,cookie有
3.session数据安全,Cookie不安全