目录
1. Cookie 从哪里来?
2. Cookie 到哪里去?
3. Cookie 有啥用?
Session
Session 中的常用方法
模拟实现一个登录页面:
cookie
Cookie 是浏览器在本地存储数据的一种机制
1. Cookie 从哪里来?
- Cookie 从服务器来
- 服务器在响应中带有 Set-Cookie 字段, 通过这个字段就可以把要保存在浏览器本地的数据给返回回去
2. Cookie 到哪里去?
- 后续浏览器访问服务器的时候, 就会把当前本地的所有cookie 都通过 http 请求, 给带过去
3. Cookie 有啥用?
- 最典型的一种应用, 就是使用 cookie保存当前用户的登录状态(用户身份信息)
在 cookie 保存用户身份标识这样的应用场景中, 此时身份标识如何分配, 以及身份信息具体如何存储(session会话), 都是需要服务器的支持的
Session
Session 就是服务器这边用来实现用户身份区分的一种机制, 通常是和 cookie 配合使用的
给当前的用户分配一个 sessionId 同时记录下当前用户的一些身份信息(可以自定义的) SessionId 就会被返回到浏览器的 cookie 中后续浏览器访服务器都会带着这个sessionId,从而能够让服务器识别出当前用户身份了
Session 中的常用方法
HttpSession getSession() :
在服务器中获取会话, 参数如果为 true ,则当不存在会话时新建会话, 单数如果为 false ,则当不存在会话时返回 null
详解:
1. getSession() 有一个参数, boolean
如果参数为 false , getSession 的行为是:
- 读取请求中 cookie 里的 sessionId
- 在服务器这边根据 sessionId 来查询对应的 Session 对象
- 如果查到了, 就会直接返回这个 session 对象 , 如果没查到, 返回 null
如果参数为 true , getSession 的行为是:
- 读取请求中 cookie 里的 sessionId
- 在服务器这边根据 sessionId 来查询对应的 Session 对象
- 如果查到了, 就会直接返回这个 session 对象
- 如果没查到, 就会创建一个 Session 对象, 同时生成一个 sessionId
以 sessionId 为 key ,Session 对象为 value, 把这个键值对存储到服务器里的一个 hash 表中, 同时把 sessionId 以 Set-Cookie 的方式返回给服务器
2. session.invalidate();
这个方法就是将session中的变量全部清空
3. session.setAttribute(key,value);
设置属性 key ,value
4. session.getAttribute(key);
获取key的值
5.session.removeAttribute(key);
删除属性为key的值
多用于实现登录功能,我们直接 ⬇
模拟实现一个登录页面:
提供两个页面 :
1. 登录页面
- 两个输入框(用户名及密码)
- 一个登录按钮
2. 主页 显示即可
服务器处理这个请求的时候就会验证用户名和密码
如果用户名密码正确, 就会跳转到主页, 并且在页面上欢迎和访问次数
第一步:
实现登录页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>-登录页面-</title>
</head>
<body>
<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="登录">
</form>
</body>
</html>
Form 会组织这里的数据以键值对的形式提交给服务器
- 其中 key 就是 input 的 name 属性
其中 value 就是 input 用户输入的内容
最终会构造成 post 请求, 在 body 里以键值对(类似于 query String) 的格式, 进行组织
服务器可以通过 getParameter 来获取到指定 key 的 value
第二步
编写 LoginServlet 处理上述登录请求
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 先从请求中拿到用户名和密码
// 为了保证读出来的参数也能支持中文, 要记得设置请求的编码方式是 utf8
req.setCharacterEncoding("utf8");
String username = req.getParameter("username");
String password = req.getParameter("password");
//2. 验证用户名和密码是否正确
if (username == null || password == null || username.equals("") || password.equals("")) {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前输入的用户名和密码不能为空!");
return;
}
//3. 假定用户名是 张三 或者 李四 . 密码是 122
//正常的登录逻辑, 验证用户名个密码都是从数据库读取的
if (!username.equals("张三") && !username.equals("李四")) {
//用户名有问题
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("用户名或密码有误");
return;
}
if (!password.equals("122")) {
//密码有问题
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("用户名或密码有误");
return;
}
//3. 用户名和密码验证 OK , 接下来就创建一个会话
//用户还没有进行登录, 测试请求的 cookie 中没有 sessionId
//这时候 getSession 是无法从服务器的 哈希表 中找到该session 对象的
//但是我们参数设为了 true , 这时候就允许 getSession 在查询未果的情况下, 创建新的 session 对象和 sessionId
//并且会自动把这个 sessionId 和 session 对象存储在 哈希表 中
//同时返回这个 session 对象, 并且 在接下来的响应中会自动把这个 sessionId 返回给客服端浏览器
HttpSession session = req.getSession(true);
//接下来可以让刚刚创建好的 session 对象存储咱们自定义的数据, 就可以在这个对象中存储用户的身份信息
session.setAttribute("username", username); //这个时间胶囊 我们在进入主页的时候就可以 挖啊挖
//4. 登录成功之后 , 自动跳转到 主页
resp.sendRedirect("index");
}
}
小结:
登录逻辑的固定套路:
- 读取用户名和密码
- 验证用户名和密码
- 创建会话 , 保存必要的用户信息
- 重定向到主页
第三步
编写生成主页的 Servlet
package login;
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;
//这个 Servlet 用来动态的生成主页面
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//此处禁止创建会话, 如果没有找到, 认为用户是未登录的状态
//如果找到了才认为是登录状态
HttpSession session = req.getSession(false);
if(session == null) {
//未登录状态
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前用户未登录!");
return;
}
String username = (String) session.getAttribute("username");
if(username == null) {
//虽然会话有对象, 但是里面没有必要的属性, 也是认为登录状态异常
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前用户未登录!");
return;
}
//如果上述的检查都 OK , 就直接生成一个动态页面
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("欢迎" + username + "进入 vvvvip 厅" );
}
}
通过抓包可以看见 cookie 就创建出来了
上面的 session 也不会一直存下去,服务器重新启动的时候, 原来 hash 表中的内容也就没了
此时再次访问, 就可能出现 sessionId 无法查询到, 于是就会被识别成 未登录状态
服务器默认保存会话, 是在内存中的, 一旦重启服务器, 之前的会话数据就没了
但是 smart Tomcat 为了方便程序员调试程序, 会在停止服务器的时候吗把会话持久化保存, 会话不会丢失 (这个取决于 smart Tomcat 版本)
访问了三次之后, 显示的界面
前面的介绍完了 现在我们来看看 session 和 cookie 的恩恩怨怨 🔽
session 和 cookie 的最官方的恩恩怨怨
Cookie和Session是Web开发中常用的两种技术,用于在服务器和客户端之间存储和跟踪用户数据。它们之间的主要区别如下:
-
数据存储位置:
- Cookie:Cookie是在客户端(通常是浏览器)上存储数据的小型文本文件。服务器将Cookie发送给客户端,然后客户端将Cookie存储在本地。每次客户端向服务器发送请求时,它都会将相关Cookie信息包括在请求头中一起发送给服务器。
- Session:Session是在服务器上存储数据的一种机制。服务器创建一个唯一的会话标识符(Session ID),并将该标识符与相关数据存储在服务器上。然后,将Session ID发送给客户端(通常通过Cookie),客户端在后续请求中将Session ID包括在请求中发送给服务器。
-
存储容量和安全性:
- Cookie:Cookie的存储容量较小,通常限制在几KB。Cookie中的数据可以由客户端修改,因此不适合存储敏感信息。Cookie可以设置过期时间,在过期之前会一直存在于客户端。
- Session:由于Session数据存储在服务器上,因此可以存储更多的数据,并且相对更安全。Session数据在客户端不可修改,只有服务器可以访问和修改。Session可以在一段时间后过期或手动删除。
-
生命周期:
- Cookie:Cookie可以设置一个特定的过期时间,也可以设置为会话Cookie(浏览器关闭后自动删除)。如果没有设置过期时间,Cookie将一直保留在客户端,直到被删除或过期。
- Session:Session可以在客户端关闭浏览器后继续保持,因为Session数据存储在服务器上。服务器可以设置Session的超时时间,以确保在一段时间内没有活动后,Session数据可以自动删除。
-
扩展性:
- Cookie:Cookie可以在不同的域名和路径之间共享,因此可以在多个网站之间跟踪用户。Cookie还可以设置为跨子域共享,但存在一些限制。
- Session:Session默认情况下与特定的域名和路径绑定。如果需要在多个域名或路径之间共享Session数据,需要进行额外的配置。
总体而言,Cookie适合存储小量非敏感数据,并在客户端之间进行共享。而Session适合存储较大量的敏感数据,因为数据存储在服务器上并且在客户端之间不可修改。选择使用Cookie还是Session取决于具体的应用需求和安全性要求。