文章目录
- Cookie 的四个问题
- Cookie 的典型应用
- Cookie 与 Session 的区别
- 代码示例体现两者的关联关系
- 1. 设计思路
- 2. 编写前端登录页面
- 3 编写 LoginServlet 处理登录请求
- 3.1 服务器是如何组织会话的
- 4. 编写 IndexServlet 生成主页
- 4.1 抓包观察交互过程
Cookie 的四个问题
1、Cookie 是什么?
这里是浏览器提供的持久化存储数据的机制。
2、Cookie 从哪里来?
Cookie 是从服务器返回给浏览器的。
服务器代码中由程序员决定要把什么样的信息保存到客户端这边。
通过 HTTP 响应的 Set-Cookie 字段,把键值对写回去即可。
3、Cookie 到哪里去?
Cookie 会在后续浏览器访问服务器的时候带到请求的 header 中发给服务器。
4、Cookie 会存储在哪里?
存储在浏览器(客户端)所在主机的硬盘中,浏览器会根据域名来分别存储。
Cookie 的典型应用
Cookie 的应用是有很多的,这里的指的应用是 标识用户的身份信息。
一开始登录的时候,服务器是不知道我的身份信息的,这个时候淘宝会查询数据库,验证用户名和密码是否正确。
如果正确,则登录成功,淘宝就会把当前用户的身份信息在内存中也保存一份,
同时会给这个用户分配一个表示身份的序号,这个序号是唯一的,可以是整数或者字符串。
把生成的唯一身份序号称为 sessionld。
服务器会使用像 hash 表这样的结构把序号作为 key,身份信息作为 value 存储起来。
服务器把生成的这些键值对称为 session(会话)
在后续的请求中,服务器收到 Cookie 中的身份序号,就会查询上述的 hash 表,判定用户是谁。
如果查到了,就知道用户是谁了,这是为了避免重复输入账号和密码;
如果没查到,就会要求用户重新登录。
所谓的过期,可能只是客户端把 cookis 删除了,也可能是服务器把对应的身份信息删了。
凡是越敏感(花钱)的网页,就越是需要设定过期,比方说,有人在公共电脑上登陆了淘宝,
下机的时候,没有手动点击注销,下一个使用你这个电脑人就能看到你的登录状态。
Cookie 与 Session 的区别
Cookie 是客户端的存储机制,Session 是服务器的存储机制。
Cookie 不仅可以存键值对,还可以存别的,Session 则是专门用来保护用户的身份信息的。
Cookie 完全可以在不搭配 session 的情况下单独使用(实现非登录场景)
Session 也可以不搭配 Cookie 使用。(手机 app 登录服务器,服务器也需要 Session,此时就没有 Cookie 的概念) Cookie 跟浏览器强相关的。
Cookie 是属于 HTTP 协议中的一个部分,
Session 则是可以和 HTTP 无关(TCP、websocket…也可以用 session)
代码示例体现两者的关联关系
1. 设计思路
这个示例中涉及到了两个页面:
1、登录页面
2、主页面
还涉及到了两个 Servlet:
1、处理登录的 LoginServlet 判定用户名密码
2、构造主页面的 IndexServlet
2. 编写前端登录页面
首先要在 webapp 目录下建一个 login.html 文件,选择 vscode 打开。
在这个文件里编写前端页面的代码。
<body>
<form action="login" method="post">
<input type="text" name="usernmae">
<br>
<input type="password" name="password">
<br>
<input type="submit" value="提交">
</form>
</body>
</html>
启动服务器,在地址栏输入路径查看效果。
接下来抓包观察结果。
这里的 POST 与 login 就对应上面代码中的 action 和 method 属性里的值。
由于我们仅仅只是实现了一个前端页面,所以此处汇报一个 404 错误。
3 编写 LoginServlet 处理登录请求
首先要创建一个 login 包,在这个包里创建一个 LoginServlet 类。
1、获取用户名和密码
这里的两个字符串要对应到前端代码中的 input 标签中的 name 属性的值。
注解里的值要对应上 form 标签里的 action 属性的值,也就是 login。
2、验证用户名和密码是否正确
if (!username.equals("zhangsan")) {
// 登录失败!!!
// 重新定向到登录页面
System.out.println("登录失败,用户名错误!!!");
resp.sendRedirect("login.html");
return;
}
if (!password.equals("123456")) {
// 登录失败!!!
// 重新定向到登录页面
System.out.println("登录失败,密码错误!!!");
resp.sendRedirect("login.html");
return;
}
此处直接规定一个用户名和密码,用户名: zhangsan;密码 : 123456
3、登陆成功的操作
// 登录成功!!!
// 1.创建一个会话
HttpSession session = req.getSession(true);
// 2.把当前的用户名保存到会话中,此处的 HttpSession 又可以当做一个 map 来使用
session.setAttribute("username", username);
// 3.重定向到主页
resp.sendRedirect("index");
第一步创建一个会话,所谓的 会话 是一个键值对,key 是 sessionld,value 是 HttpSession 对象。
每个客户端登陆的时候都有一个这样的键值对,也就是会话。
服务器要管理多个这样的会话,服务器可以搞一个哈希表,把这些会话组织起来。
HttpSession session = req.getSession(true);
getSession(true) 表示判定当前的请求是否有对应的会话了,也就是拿着请求中的 cookie 里的sessionld 查一下哈希表。
如果 sessionld 不存在,或者没查到就会创建新会话,并插入到哈希表中。
如果查到了,就直接返回插到的结果。
创建新会话的过程:
1.构造一个 HttpSession 对象
2.构造唯一的 sessionld
3.把这个键值对插入到哈希表
4.把 sessionld 设置到响应报文 Set-Cookie 字段中。
3.1 服务器是如何组织会话的
上图中的最外层矩形代表一个服务器,每一个 会话 都是由 key 和 value 组成的。
每个会话是一个键值对,对应到一个客户端,服务器这里可以对应到多个客户端,也就是多组会话。
每个会话对象里还可以存储一些程序员自定义的数据,以键值对形式组织的。
4. 编写 IndexServlet 生成主页
首先要在 Login 目录下创建一个 IndexServlet 类。
这里的注解要和 LoginServlet 类中的重新定向到主页是一致的。
@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) {
// 此时未登录
System.out.println("用户未登录!");
// 返回到登录页面
resp.sendRedirect("login.html");
return;
}
// 此时为登录
String username = (String)session.getAttribute("username");
// 构造页面
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("欢迎" + username + "回来!");
}
}
String username = (String)session.getAttribute(“username”);
这条语句,是用来获取登录的用户名的,前提是前面的登录操作中存过。
由于 HttpSession value 的类型是 Object 类型,需要手动强制类型转成 String。
username 是在 LoginServlet 中保存好的,根据同一个 sessionId 得到了同一个 HttpSession 对象。
4.1 抓包观察交互过程
上述的登录过程就像是去医院看病一样。
首次到达医院,需要挂号办理就诊开。(类似于登录、创建会话、分配 sessionId)
你的身份信息就进入医院的系统了,发出来的就诊卡里就包含了你的 sessionId
后续去具体的科室检查的时,比如说进入内科,医生开始检查,检查信息就进入了系统,相当于是我的 HttpSession 中设置了一些 attribute。
来到检验科抽血时,也是先刷卡,医生把抽血的结果也是设置到系统中的。在我的 HttpSession 中又设置了一些 attribute。
来到影像科室拍片时,医生也是先刷卡,也是把拍片结果设置到系统中。
再次回到内科的时候,医生直接就在系统上看到结果了。
每次刷卡都是拿着我的 sessionId 来查系统,获取到会话对象进一步得到里面的 attribute,
就知道要哪些检查和结果是什么了。
你的就诊卡就是 cookie 里面存的就是 sessionId。