Cookie 与 Session
什么是会话?
会话的过程客户端打开浏览器,通过 URL 地址发起 HTTP 请求,服务器接收请求并做出相应处理,再把处理结果返回至客户端,客户端接收数据并显示渲染,最后关闭浏览器。这整个过程就是一次会话。
会话的使用场景与基本原理
会话的使用场景:偏好记录、自动登录、浏览记录等。
会话的原理:在客户端或服务端保存用户信息数据,从而记录用户的信息和浏览行为。有两种实现会话的方式:Cookie 和 Session。
Cookie 有哪些特点?
Cookie的会话数据保存在客户端;在每个站点下限制在 20 个Cookie 以内,每个 Cookie 不超过 4k。Cookie 的安全性相对较低。
Cookie 的工作流程是怎样的?Cookie 在客户端的保存是一直有效的吗?
某客户端第一次访问(登录)服务端时,服务端生成一个 Cookie 返回给客户端,客户端收到 Cookie后将其保存在客户端;之后再次与服务器发生交互时,会携带上这个 Cookie,从而实现了会话记录。我们可以使用 setMaxAge 来设置 Cookie 的有效期;默认情况下会话结束 Cookie 就失效。
Cookie 测试示例代码如下:
// TestCookie.java
public class TestCookie extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html;charset=UTF-8");
RequestDispatcher dispatcher = null;
// 获取用户登录的用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
// 创建两个 Cookie 对象
Cookie userCookie = new Cookie("username", username);
Cookie passCookie = new Cookie("password", password);
// 设置 Cookie 过期时间
userCookie.setMaxAge(2 * 60); // 两分钟后过期
passCookie.setMaxAge(2 * 60);
// 把 Cookie 添加到响应体中云
res.addCookie(userCookie);
res.addCookie(passCookie);
// 从请求对象中取出 Cookie
Cookie[] cookies = req.getCookies();
if (cookies != null) { // 不是第一次访问(登录)时
for (Cookie cookie: cookies) {
if (cookie.getName().equals("username")) {
username = cookie.getValue();
}
if (cookie.getName().equals("password")) {
password = cookie.getValue();
}
}
}
try {
PrintWriter out = res.getWriter();
if (username.equals("admin") && password.equals("123456")) {
out.println("<h1>admin 用户登录成功</h1>");
out.close();
} else {
out.println("<h1>登录错误</h1>");
out.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
// index.html
<form method='GET' action='/servlet-lesson/TestCookie'>
<div>
<span>用户名</span><input type='text' name='username' />
</div>
<div>
<span>用户名</span><input type='password' name='password' />
</div>
<input type='submit' value='GET提交' />
</form>
// web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0">
<display-name>Servlet</display-name>
<servlet>
<servlet-name>TestCookie</servlet-name>
<servlet-class>
cn.geekxia.TestCookie
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestCookie</servlet-name>
<url-pattern>/TestCookie</url-pattern>
</servlet-mapping>
</web-app>
Session 是怎么工作的?
Session的工作过程Session的工作过程:当客户端第一次访问服务端时,服务端会生成一个唯一的 SessionId 编号,同时服务端会存储客户端的用户信息,并把 SessionId 写入到响应体的 Cookie 中;当客户端接收到响应体中的 Cookie后,会将存储在客户端,之后再次访问服务器时,都会带上这个 Cookie;之后每次请求,服务端会根据请求体中 Cookie 中的 SessionId 来读取存储在服务端的用户信息,从而识别用户并记录用户的相关行为,进一步为客户端用户提供个性化的数据。
Session 的生命周期
Session 默认有效期是 30 分钟。使用 setMaxInactiveInterval 方法可以设置 Session 的有效期,还可以使用部署描述符来设置其有效期,还可以调用 invalidate 方法来手动地让 Session 失效。(注意:使用接口方法对 Session 设置,其优先级高于部署描述符的 Session 设置。)
Session 测试示例代码如下:
// TestSession.java
public class TestSession extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html;charset=UTF-8");
// 获取用户登录的用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
// 创建一个 Session 对象
HttpSession session = req.getSession();
// 设置 Session 对象的过期时间
session.setMaxInactiveInterval(2 * 60);
// 手动设置 Session 过期
// session.invalidate();
// 从 Session 对象中读取用户信息。如果是第一次访问,Session 中是没有用户信息的
String name = (String)session.getAttribute("username");
PrintWriter out = res.getWriter();
if (name != null) { // 再次访问时
out.println("<h1>"+name+" 再次访问,自动登录</h1>");
out.close();
} else { // 第一次访问时
out.println("<h1>"+name+" 第一次访问</h1>");
out.close();
}
// 把用户信息保存到 Session 对象中去,保存在服务端。这样的Session 是存储在服务端的内存中的。
session.setAttribute("username", username);
// 当客户端第一次访问时,会以 Cookie的方式向客户端写入一个名为 JSESSIONID 的 Cookie。
// 客户端再次访问时,便可以些来读取服务端中 Session 对象中所存储的用户信息了。
}
}
// index.html
<form method='POST' action='/servlet-lesson/TestSession'>
<div>
<span>用户名</span><input type='text' name='username' />
</div>
<div>
<span>用户名</span><input type='password' name='passname' />
</div>
<input type='submit' value='POST提交' />
</form>
// web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0">
<display-name>Servlet</display-name>
<session-config>
<session-timeout>2</session-timeout>
</session-config>
<servlet>
<servlet-name>TestSession</servlet-name>
<servlet-class>
cn.geekxia.TestSession
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestSession</servlet-name>
<url-pattern>/TestSession</url-pattern>
</servlet-mapping>
</web-app>
上述部署描述符中,<session-config> 用于统一对 Session 进行配置,<session-timeout> 用于配置 Session 过期时间,其单位是分钟,其优先级比接口 API 对Session设置的优先级要低。
关于 Cookie 和 Session 的差异对比与小结:
前者存储在客户端,相对不安全;后者存储在服务端的内存中,相对较安全。
前者的生命周期是累加的,到时间后就失效;后者的生命周期是间隔的,即以最后一次访问时开始计时,间隔时间大于有效期时间才会失效。
前者在每个站点下最多只能有 20 个Cookie,且每个 Cookie 不能大于 4k。后者是存储在服务端的内存中的,所以 Session最好不要用来存储过大的对象。
本节完!!!