web程序是通过HTTP协议传输的,而HTTP是一个无状态的协议,当一个客户端向服务器发送请求,在服务器返回响应后,连接就关闭了,在服务器器端不保留连接信息。当客户端发送多次请求且需要相同的请求参数的时候,就还需要重传。这样如果数据量很大的情况下,效率就会大打折扣。Cookie的出现就是为了解决这个问题。
Cookie的工作流程:
客户端第一次请求时携带数据发送给服务器,服务器这边决定将哪个数据用Cookie存储,并通过响应将Cookie存在响应报文中的header中返回给客户端,然后客户端这边会存储在浏览器上或硬盘中。之后每次HTTP请求中自动携带这个Cookie给服务器。它位于header中的一个属性,键值对结构。
Cookie的缺点:
数量有限,单个存储大小有限,安全性无法得到保障,浏览器可以禁用cookie。如果用户禁用cookie,则无法使用cookie。
Cookie的生存周期:
可以根据需求设置。分为临时Cookie和持久化Cookie,临时Cookie时=是储存在内存中的,当浏览器关闭的时侯,Cookie自动失效。持久化Cookie是保存在浏览器中的某个存储目录,当时间过期之后才会失效。有些页面将Cookie的生存周期设置为0或者负值,这样在关闭浏览器时,就会马上消除Cookie,不会记录用户的信息,更加安全。上述失效指的都是浏览器这边删除了Cookie。
Cookie的应用场景:
对于安全性不高的数据,数据量不大的数据存储比较合适。可以用来处理客户端发送不同请求的时候如何使用相同的参数信息。
cookie可以用来保存用户的登录信息。比如10天内免登陆等等。如果删除cookie下次就需要重新登陆。
Cookie练习:实现一周内免登录。
Title
Title
登陆成功
// 登录操作
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String memory = req.getParameter("memory");
//先判断输入是否完整
if(username==null || password==null || "".equals(username) || "".equals(password)) {
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("用户名或密码不能为空");
return;
}
//再判断是否存在该用户 去数据库中查找 这里省略 默认存在
//再判断用户有没有点击免登录操作
if(Boolean.valueOf(memory)) {
//说明点击了免登录操作,就要进行创建Cookie对象
//创建Cookie对象
Cookie cookie1 = new Cookie("username",username);
Cookie cookie2 = new Cookie("password",password);
//设置有效访问路径
cookie1.setPath("/");
cookie2.setPath("/");
//设置Cookie时间 单位秒
cookie1.setMaxAge(7*24*3600);
cookie2.setMaxAge(7*24*3600);
//向客户端返回Cookie信息
resp.addCookie(cookie1);
resp.addCookie(cookie2);
}
//跳转到主页面
resp.sendRedirect("main.html");
}
}
//每次访问登录页面时,前端ajax都会向这段代码(后端)发送请求
//检验是否有cookie
@WebServlet("/cookie")
public class CookieServlet extends HttpServlet {
private ObjectMapper mapper= new ObjectMapper();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//先获取Cookie
Cookie[] cookies = req.getCookies();
// if(cookies==null) {
// return;
// }
if(cookies!=null && cookies.length>0) {
//说明请求中有Cookie
for (Cookie cookie : cookies) {
//获取用户名
if("username".equals(cookie.getName())) {
String username = cookie.getValue();
}
//获取密码
if("password".equals(cookie.getName())) {
String password = cookie.getValue();
}
}
//在数据库中进行匹配 这里逻辑由自己编写 默认匹配成功
//重定向到主页面
Demo demo = new Demo("main.html");
resp.setStatus(278);
resp.setContentType("application/json");
resp.getWriter().write(mapper.writeValueAsString(demo));
}else {
resp.setContentType("text/html;charset=utf8");
resp.sendRedirect("login.html");
}
}
}
会话:用户打开一个浏览器,点击多个超链接,访问服务器多个web资源然后关闭浏览器,整个过程称之为一个会话。
Session的工作流程:
假设一个网站对应一个 webapp, 而 webapp 必然储存着大量用户的会话 Session, 存储的结构是类哈希表结构, 一个会话的Key 值是 服务器分配的 id, 即 sessionId, 这个Key对应的value(HttpSession)是这个用户的个人信息, 也是以键值对的形式组织的。
最外面的两个sessionId和HttpSession是以键值对形式存储在哈希表上。其中sessionId作为一个键存在,HttpSession对象本身作为一个值存在,而HttpSession对象里面的一些属性又是以键值对形式存储。即就是键值对的值里又套了一个键值对。
Session的生命周期:
可以根据需求设置。默认是30分钟。举个例子,如果设为10分钟的话,当你登录一个服务器,登陆成功的话,服务器会返回一个sessionId,登陆成功之后的10分钟内没有客户端这边进行任何HTTP请求,10分钟后你再发送一个HTTP请求,就会提示你需要重新登陆。
每次登陆的时候会重新创建会话,服务器重新返回sessionId,客户端通过请求中携带的id可以不断访问该web程序的多个界面,生命周期结束有常见的两种,用户主动点击退出登录(注销)或一段时间内没有进行操作。后面用户再次登录时就需要重新登陆,重新创建会话以及服务器返回新的sessionId。以此循环。注销就是服务器那边通过代码逻辑消除了会话对象。id也消除了。客户端这边再次请求时id就会无法匹配,就需要重新登陆。一段时间内不操作也是如此。
Session的应用场景:
判断一个用户是否是登录状态,非登录状态强制跳转到登录页面。不是所有用户都会先进入登录页面输密码,有可能他直接在地址栏里强行输入主界面或其他操作界面的URL,这个时候就会出现问题。我们可以使用Session,当用户登录的时候为他设置一个session对象,直至退出登录,该session销毁。并在每个页面里加入判断是否存在session对象,不存在就强制跳转到登录页面。
进一步想要提高安全性,可以对sessionId增加时间和空间上的显示,异地需重新登录,一段时间后需要重新登陆。
代码示例,登录时创建会话:
// 验证通过 进行登录 创建会话 使用该会话创建用户信息
// true表示会话存在就查找 不存在就创建新的会话
HttpSession session = req.getSession(true);
// 会话保存操作 后续通过第一个参数获取到会话
session.setAttribute("user",user);
// 进行重定向 跳转到主页面 重定向使得登录成功操作不能去回转
resp.sendRedirect("mainInterface.html");
代码示例,获取会话:
// 使用这个方法来获取用户的状态
// false的作用 有会话返回对象 无会话则返回null
HttpSession session = req.getSession(false);
if(session == null) {
//说明无会话 表明该用户是未登录状态
//创建一个空的用户对象
User user = new User();
//将空对象的内容以json格式进行响应
String respJson = mapper.writeValueAsString(user);
resp.getWriter().write(respJson);
return;
}
//获取会话对象
User user = (User) session.getAttribute("user");//与上面保存会话的key值要一样
两者区别:
Cookie可以存储在浏览器或本地硬盘上,Session只能存储在服务器上。
Session比Cookie更安全。
Session占用服务器资源和性能,Session过多,会增加服务器压力。
Cookie在浏览器这边存储,浏览器对cookie的存储有限制,个数一般不超过20个,单个Cookie存储的数据不超过4k。Session没有大小限制,它与服务器的内存大小有关。
Session能存储任意类型的Java对象(类似于哈希表结构存储),Cookie只能存储String类型的对象。(以键值对结构存储)