目录
Cookie的几个问题
1.Cookie是什么
2.Cookie从哪里来
3.Cookie到哪里去
4.Cookie存储在哪里
Cookie最典型的应用
实现模拟登录代码
整体流程
登录页面
LoginServlet
IndexServlet.
交互过程
浏览器提供的持久化存储数据的机制.浏览器有限制的访问本地的文件系统.
Cookie从服务器返回给浏览器.
服务器代码中由程序员决定要把什么样的信息保存到客户端这边,通过http响应的Set-Cookie字段,把键值对写回到客户端这边.
Cookie会在后续浏览器访问服务器的时候带到请求的header中,发给服务器.
为什么从服务器来又回到服务器,这么折腾?
要始终牢记服务器不是只给一个客户端提供服务,服务器同一时刻可能要处理多个客户端,此时服务器就可以通过Cookie中的值,来识别当前客户端是谁,当前客户端的服务提供到哪个环节了.(相当于是客户端通过Cookie来向服务器自报家门)
存储在浏览器(客户端)所在主机的硬盘中.浏览器会根据域名来分别存储.Cookie不是只有一个,而是有很多.根据不同的域名存储不同的Cookie.
Cookie的用途很多,但最典型的应用就是用来表示用户的身份信息.
过期:可能是客户端把Cookie删除了,也可能是服务器把对应的身份信息删除了.
Cookie和Session之间的关联和区别
关联:在网站的登录功能中,需要搭配使用.
区别:Cookie是客户端的存储机制.Session是服务器的存储机制.
Cookie里面可以存储各种键值对.Session则专门用来保存用户的身份信息.
Cookie完全可以单独使用,不搭配Session.(非登陆场景下)
Session也可以不搭配Cookie使用(手机app登录服务器,服务器也需要Session,此时就没有Cookie的概念),Cookie是跟浏览器强相关的.
Cookie是属于HTTP协议的一个部分.
Session则可以和HTTP无关(TCP,websocket等等也可以用Session).
1.登录页面输入用户名和密码,和一个提交按钮,点击按钮触发一个登录请求.
2.LoginServlet,验证用户名密码是否正确
3.如果登录成功,跳转到主页(IndexServlet).在主页中显示用户名字.
整体流程设计到两个页面:
1.登录页面
2.主页面
涉及到两个Servlet:
1.处理登录的LoginServlet判定用户名和密码
2.构造主页面的IndexServlet.
登录
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;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
//验证用户名密码是否正确
//正常情况下,用户名密码会使用数据库来保存
//此处我们直接写死,约定合法的用户名是zhangsan 和 lisi
//密码合法的是123
if (!username.equals("zhangsan") && !username.equals("lisi")){
//登陆失败
//直接重定向到登录页面
System.out.println("登陆失败,用户名错误!!!");
resp.sendRedirect("login.html");
}
if (!password.equals("123")){
//登陆失败
System.out.println("登陆失败,密码错误!!!");
resp.sendRedirect("login.html");
}
//登陆成功
//1.创建一个回话
HttpSession session = req.getSession(true);
//2.把当前的用户名保存到会话,此处的HttpSession 又可以当成一个Map来使用
session.setAttribute("username",username);
//3.重定向到主页
resp.sendRedirect("index");
}
}
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;
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
//重定向发起的是get请求
@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 + "回来!");
}
}
HttpSession session = req.getSession(true);
getSession(true);判定当前请求是否已经有对应的会话了(拿着请求中的cookie里的sessionid查哈希表),如果sessionId不存在,或者是没有查到,就创建新会话,并插入到哈希表中,如果查到了,就直接返回查到的结果.
创建过程:
1.构造一个HttpSession对象
2.构造唯一的sessionId
3.把这个键值对插入哈希表
4.把sessionId设置到响应报文中(Set-Cookie字段中)
需要注意的是,HttpSession对象本身也是一个键值对,setAttribute和getAttribute两个方法来存取键值对,这里的键值对是程序员自定义的数据.
使用fildder抓包,查看具体交互过程.
第一次交互:
请求
注意,这次请求中,没有cookie.
响应:
设置了sessionId,并重定向.
第二次交互:
请求
这个请求到达服务器,Servlet会在getSession方法中,根据sessionId来查询HttpSession对象.
响应:
只要完成登录之后,后续请求多次服务器,都会带上刚才cookie的值(sessionId).