Cookie & Session
参考资料:cookie和session的详解与区别 - 测试开发喵 - 博客园 (cnblogs.com)
1. 会话
会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。
-
Cookie通过在客户端记录信息确定用户身份,
-
Session通过在服务器端记录信息确定用户身份。
1.1 Cookie机制
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
查看某个网站颁发的Cookie
在浏览器地址栏输入javascript:alert (document. cookie)就可以了(需要有网才能查看)。JavaScript脚本会弹出一个对话框显示本网站颁发的所有Cookie的内容。
1.2 Seesion机制
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。
2. 保存会话的两种技术
Cookie
- 客户端技术(响应,请求)
Session
- 服务器技术(可保存用户的会话信息,将信息或数据放在Session中)
- 常见场景:登录一次后,一定时间内自动登录
3. Cookie
- 从请求中拿到cookie信息
- 服务器响应给客户端cookie
// 用到的方法
Cookie[] cookies = req.getCookies(); // 获得cookie
cookie.getName() // 获取cookie的名称
cookie.getValue() // 获得cookie的内容
new Cookie("name", "value") // 新建一个cookie
cookie.setMaxAge(); // 设置cookie有效期(以秒为单位)
resp.addCookie(cookie); // 相应给客户端一个cookie
Demo: 设置cookie为当前访问时间,并记录上一次访问时间
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决中文乱码
resp.setContentType("text/html;charset=utf-8"); // 解决页面显示中文乱码
req.setCharacterEncoding("utf-8"); // 解决控制台输出中文乱码
resp.setCharacterEncoding("utf-8");
// 响应:给前端传数据
PrintWriter out = resp.getWriter();
// Cookie: 服务器从客户端获取
Cookie[] cookies = req.getCookies(); // cookie是一个数组,即Cookie可能存在多个
// 判断Cookie是否存在
if (cookies != null){
out.write("您上一次访问的时间是:");
//遍历Cookie数组
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
// 获取Cookie的名字
if (cookie.getName().equals("lastLoginTime")) {
// 获取Cookie中的值
Long lastLoginTime = Long.parseLong(cookie.getValue()); // 将Cookie值这一字符串转为长整型
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString()); // 将Date转为字符串
}
}
}else {
out.write("这是您第一次访问。");
}
// 服务器给客户端响应一个Cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// 设置cookie的有效期为1天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
- cookie一般会保存在本地的用户目录下appdata;
一个网站的cookie是否有上限:
- 一个cookie只能保存一个信息;
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
- cookie大小有限制4kb;
- 300个cookie浏览器上限.
删除cookie
- 不设置有效期, 关闭浏览器, 自动失效;
- 设置有效期为0.
中文乱码问题
// 先编码:
URLEncoder.encode("字符串","UTF-8")
// 再解码:
URLDecoder.decode("字符串","UTF-8")
4. Session(重点)
什么是Session:
- 服务器会给每一个用户(浏览器)创建一个Session对象;
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
- 用户登陆之后,整个网站都可以访问。(例如:保护用户信息;保存购物车信息……)
Demo01:获取session的值
SessionDemo01.java
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决乱码问题
resp.setContentType("text/html;charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
req.setCharacterEncoding("UTF-8");
// 得到一个session
HttpSession session = req.getSession();
// 给session存东西,键值是object,可以是一个对象
session.setAttribute("name", new Person("法外狂徒张三",99));
// 获取session的id
String sessionId = session.getId();
// 判断session是不是新创建的
if (session.isNew()){
resp.getWriter().write("session创建成功"+sessionId);
} else {
resp.getWriter().write("session在服务器中已经存在,ID为:"+sessionId);
}
}
SessionDemo02.java
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决乱码问题
resp.setContentType("text/html;charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
req.setCharacterEncoding("UTF-8");
// 得到一个session
HttpSession session = req.getSession();
// 获取Demo01定义的session值
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
}
Person.java
public class Person {
private String name;
private int age;
// get、set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 构造函数:有参构造、无参构造
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
// toString()
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
输出:
Person{name='法外狂徒张三', age=99}
文件结构
使session失效的两种方法
-
移除session的属性、注销session.
session.removeAttribute("name"); //移除属性 session.invalidate(); //注销session
-
设置失效时间(session-timeout)
<!--设置session默认的失效时间--> <session-config> <!--默认session15分钟后自动失效,以分钟为单位--> <session-timeout>15</session-timeout> </session-config>