当前位置: 首页 > news >正文

Cookie 与 Session概述

        在 Web 开发中,会话跟踪是一个核心问题。HTTP 协议是无状态的,这意味着服务器无法直接记住客户端的状态。而 Cookie 和 Session 技术的出现,正是为了解决这一难题。

一、Cookie概述

        Cookie,翻译成中文是小甜点、小饼干的意思。在 HTTP 协议中,它代表着服务器送给客户端浏览器的 “小甜点”。实际上,Cookie 就是由一个键和一个值构成的信息,会随着服务器端的响应发送给客户端浏览器。客户端浏览器会将其保存起来,等下一次访问该服务器时,再把 Cookie 发送回服务器。

Cookie 的规范

不用担心 Cookie 会占满你的硬盘,因为它有严格的规范限制:

  • 一个 Cookie 最多只有 4KB 大小。
  • 浏览器最多可以保存 300 个 Cookie。

        不过,在浏览器竞争的大环境下,一些浏览器对 Cookie 规范进行了 “扩展”,比如有的浏览器允许每个 Cookie 为 8KB,最多可保存 500 个 Cookie,但即便如此,也不会出现占满硬盘的情况。另外,不同的浏览器之间是不能共享 Cookie 的。

Cookie 的作用

        Cookie 的核心作用就是 “跟踪客户端状态”。服务器把信息保存在客户端,客户端下次请求时再把这些信息还给服务器,服务器就能通过这些信息识别客户端了。

Cookie 的基本操作

  1. 保存 Cookie 到客户端:这是响应工作的一部分,通过 HttpServletResponse 类的void addCookie(Cookie c)方法来实现,该方法可多次调用以添加多个 Cookie。例如:
Cookie cookie = new Cookie("username", "txjava");
response.addCookie(cookie);

        这样,在响应头中就会添加 Set - Cookie 的值,客户端浏览器也会保存该 Cookie。当下一次访问服务器时,请求头中就会带着这个 Cookie 的值。

  1. 服务器端读取 Cookie:浏览器保存 Cookie 后,会在下次请求时把 Cookie 放到请求头中发送给服务器,服务器可通过 HttpServletRequest 的Cookie[] getCookies()方法读取。示例如下:
Cookie[] cookies = request.getCookies();
if(cookies != null){for(Cookie cookie : cookies){System.out.println(cookie.getName() +":"+ cookie.getValue());}
}

Cookie 的生命周期

        Cookie 的存活时间取决于其生命周期设置,默认情况下,Cookie 只在浏览器内存中存活,关闭浏览器后就会消失。可通过Cookie#setMaxAge(int expiry)方法设置存活时间(参数为秒数):

  • cookie.setMaxAge(60*60*24*30*12):表示 Cookie 可存活 1 小时(此处原文档描述有误,60*60 才是 1 小时),此时浏览器不仅会把 Cookie 保存在内存中,还会保存到硬盘上,即便关闭浏览器、重启电脑,Cookie 也会存在 1 小时。
  • cookie.setMaxAge(-1):这是默认值(其实只要是负数都一样),表示 Cookie 只在浏览器内存中存活,关闭浏览器窗口后就会消失。
  • cookie.setMaxAge(0):表示 Cookie 被作废,既不在内存中存活,也不在硬盘上存活,目的是覆盖客户端原来的该 Cookie 使其失效。

Cookie 的路径

        Cookie 有一个 path 属性,可通过Cookie#setPath(String)方法设置。若不设置,其默认路径就是请求的路径。比如请求http://localhost:8080/cookie_demo/path时,服务器响应的 Cookie 默认路径是/cookie_demo;请求http://localhost:8080/cookie_demo/path/son时,默认路径是/cookie_demo/path

Cookie 路径的作用是决定服务器的请求是否会从浏览器中加载某些 Cookie。例如,有两个 Cookie:

  • cookie1:name=path1;value=pathvalue1;path=/cookie_demo
  • cookie2:name=path1;value=pathvalue2;path=/cookie_demo/path

        当访问http://localhost:8080/cookie_demo/*时,请求头中会包含 cookie1,不包含 cookie2;当访问http://localhost:8080/cookie_demo/path/*时,请求头中会包含 cookie1 和 cookie2。也就是说,访问子路径时会包含父路径的 Cookie,访问父路径时不包含子路径的 Cookie。

        若想在 BServlet 中设置的 Cookie,在客户端访问 AServlet 时也能包含在请求头中,可设置 BServlet 中 Cookie 的 path,如c2.setPath(“/cookie_demo”)(硬编码)或c2.setPath(request.getContextPath() + “/”)(活编码)。

Cookie 保存中文

        Cookie 中不能直接设置中文,但可先使用URLEncoder.encode()方法编码后再存放,获取时先使用URLDecoder.decode()方法解码。

  • 添加 Cookie:
Cookie cookie1 = new Cookie("username", URLEncoder.encode(username,"UTF-8"));
  • 读取 Cookie:
Cookie[] cookies = request.getCookies();
if(cookies != null){for(Cookie cookie : cookies){if(cookie.getName().equals("username"))username = URLDecoder.decode(cookie.getValue(),"UTF-8");if(cookie.getName().equals("password"))password = cookie.getValue();}
}

Cookie 的浏览器管理

  1. Google Chrome:查看 Cookie 可通过相关入口操作;清理 Cookie 则在设置 - 隐私设置和安全性 - 清除浏览数据中进行。
  2. Firefox:查看 Cookie 有相应的操作入口;清理 Cookie 在选项 - 隐私与安全 - Cookie 和网站数据 - 清除数据中进行。

Cookie 的禁用

        默认情况下浏览器启用 Cookie,手动禁用后,绝大多数互联网网站无法登录,这与后续要讲的 session 有关。判断浏览器是否禁用 Cookie,可通过尝试获取刚刚添加的 Cookie,若获取不到,则说明 Cookie 被禁用。

二、HttpSession:服务器端的会话对象

HttpSession 概述

        Session 也是域对象之一,其范围在一个会话范围内有效,拥有getAttribute()setAttribute()等系列方法。在一个会话内共享一个 session 对象,可保存会话内的数据,如当前用户的信息。

目前所学域对象的作用范围:ServletContext > HttpSession > HttpServletRequest。

        获取 session 对象可使用request.getSession()方法。有了 session,就无需再用 Cookie 跟踪会话,但 session 的生命周期相对较短,用户关闭浏览器窗口后,session 就会失效。

HttpSession 原理(依赖 Cookie)

HTTP 是无状态协议,但 session 能跟踪会话状态,这是因为 session 依赖 Cookie。

  • 客户端第一次访问服务器时,服务器会为其创建一个 session 对象,放入 session 池中,并在响应时通过 Cookie 将 sessionId 发送给客户端。只有第一次访问时,服务器才会创建 session 并响应 sessionId。
  • 客户端再次访问服务器时,会在请求中带着 sessionId,服务器通过 sessionId 到 session 池中找到对应的 session 对象,从而完成会话跟踪。服务器端保存 session 对象,客户端只保存 sessionId,用户在 session 中保存的数据就能被再次使用。

发送 sessionId 的 Cookie 的 maxAge 为 - 1,即只在浏览器内存中存在,关闭所有浏览器窗口后,该 Cookie 就会消失。

HttpSession 失效

session 失效主要有以下几个原因:

  1. 调用session.invalidate()方法注销 session。
  2. session 超时,可在配置中设置,如:
<session-config><!-- session的超时时间,以分钟为单位 --><session-timeout>1</session-timeout>
</session-config>
  1. Cookie 被禁用,因为 session 依赖 Cookie 传递 sessionId,Cookie 禁用后,session 也会失效(不过可通过其他方式实现,如在 url 中传递 session_id)。

三、Session 和 Cookie 的区别(面试常考)

区别SessionCookie
存储位置服务器端客户端(浏览器)
存储位置默认存在服务器的一个文件里(不是内存)客户端浏览器中
运行依赖依赖 session id,而 session id 通常存在 cookie 中不依赖其他存储对象
存储位置可放在文件、数据库、内存中存于客户端浏览器
应用场景常用于用户验证等场合用于跟踪客户端状态,如保存用户偏好设置等

四、综合练习:使用 cookie 实现自动登陆

实现思路

通过在客户端保存包含用户名和密码信息的 Cookie,当用户再次访问时,服务器读取 Cookie 中的信息进行自动登录验证。

代码实现

  1. html 代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="login" method="post">用户:<input type="text" name="username"/><br><br>密码:<input type="password" name="password"/><br><br><input type="checkbox" value="1" name="auto"/>&nbsp;一天内自动登陆<br><br><input type="submit" value="登陆"/><br>
</form>
</body>
</html>
  1. Java 代码
package cn.tx.servlet;import cn.tx.model.User;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;/*** 模拟自动登陆方法*/
@WebServlet(name = "LoginServlet",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获取用户端提交的表单信息String username = request.getParameter("username");String password = request.getParameter("password");String auto = request.getParameter("auto");// 统一设置response响应格式及编码response.setContentType("text/html;charset=utf-8");response.setCharacterEncoding("UTF-8");// 判断是否提交用户信息if(username == null && password == null && auto == null){// 用来接收cookie的value信息String cookieValue = null;// 获取用户端cookiesCookie[] cookies = request.getCookies();// 如果cookies不为null  尝试获取name为txjavac的cookie的valueif(cookies != null){for(Cookie ck : cookies){if(ck.getName().equals("txjavac")){cookieValue = ck.getValue();}}}// 如果没有获取到cookie的value 返回信息if(cookieValue == null){response.getWriter().write("您还未进行登陆,请进行登陆!!!");return;}else{// 如果获取到// 对该信息进行解码BASE64Decoder decoder = new BASE64Decoder();cookieValue = new String(decoder.decodeBuffer(cookieValue));// 对解码后的字符串进行切分String[] split = cookieValue.split(":");// 获取用户名和密码username = split[1];password = split[2];// 创建用户对象User user = new User(username,password);// 获取sessionHttpSession session = request.getSession();// 把用户对象存储到session中session.setAttribute("user",user);// 返回内容response.getWriter().write("尊敬的"+username+",欢迎您!!!");return;}}// 判断用户名或密码是否正确if(username!=null && password!=null && username.equals("admin") && password.equals("txjava")){// 创建用户对象User user = new User(username,password);// 获取session会话对象HttpSession session = request.getSession();// 把用户存入session中session.setAttribute("user",user);// 用户名密码正确的话,判断是否勾选了一天内自动登陆if(auto != null && auto.equals("1")){// 拼接存储于cookie的value值String value = "txjava:" + username + ":" + password + ":" + 24*3600;// 进行BASE64编码BASE64Encoder encoder = new BASE64Encoder();value = encoder.encode(value.getBytes());// 创建cookie并且设置一天失效后添加到responseCookie cookie = new Cookie("txjavac",value);cookie.setMaxAge(24*3600);response.addCookie(cookie);}response.getWriter().write("尊敬的"+username+",欢迎您!!!");return;}else {response.getWriter().write("用户名或密码错误!!!");return;}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}

五、学习目标回顾

  • 熟练掌握 Cookie 的概念、使用及生命周期。
  • 能够使用 Cookie 存储中文并了解 Cookie 的路径作用。
  • 掌握 Session 的原理及使用方法。
  • 能够详细说明 Cookie 和 Session 的区别。
  • 能够独立完成自动登陆功能的开发。

        通过以上内容,相信大家对 Cookie 和 Session 有了较为全面的认识,在实际开发中,可根据具体需求灵活运用这两种技术来实现会话跟踪等功能

http://www.dtcms.com/a/284258.html

相关文章:

  • AI编程实战:如何让AI生成带参数和返回值的Python函数——以PDF文本提取为例
  • 【橘子分布式】gRPC(理论篇)
  • 要实现在调用  driver.get()  后立即阻止页面自动跳转到 Azure 登录页,可通过以下几种方法实现:
  • Redis完全指南:从基础到实战(含缓存问题、布隆过滤器、持久化及Spring Boot集成)
  • 前端 cookie 使用
  • 独家|理想汽车放弃华为PBC模式,回归OKR理想汽车
  • 自动化测试工具 Selenium 入门指南
  • 大带宽服务器对于高流量网站的作用
  • Kubernetes v1.33:容器生命周期管理的重要演进
  • 断网情况下,网线直连 Windows 笔记本 和Ubuntu 服务器
  • python的抗洪救灾管理系统
  • 分布式系统中脑裂问题
  • 数据结构入门 (二):挣脱连续空间的束缚 —— 单向链表详解
  • LiteCloud超轻量级网盘项目基于Spring Boot
  • 大模型AI制作svg流程图过分简单粗糙单调的问题及修改调整方法
  • AI大模型教程 Langchain AI原生应用开发 Milvus AnythingLLM Dify 仿京东《京言》AI实战解析
  • 【赵渝强老师】Redis的主从复制集群
  • mongodb-org-server_8.0.11_amd64.deb 这个文件怎么安装
  • Java爬虫与正则表达式——用正则来爬取数据
  • 二刷 黑马点评 秒杀优化
  • 板凳-------Mysql cookbook学习 (十二--------1)
  • 医院各类不良事件上报,PHP+vscode+vue2+element+laravel8+mysql5.7不良事件管理系统源代码,成品源码,不良事件管理系统
  • React事件处理
  • 【FFmpeg 快速入门】本地播放器 项目
  • c++:explicit关键字
  • Python枚举技巧:轻松获取索引与值
  • 【Linux手册】缓冲区:深入浅出,从核心概念到实现逻辑
  • Python爬虫入门到实战(2)-selenium驱动浏览器
  • 8.预处理-demo
  • 建筑兔零基础人工智能自学记录111|初识comfyui-20