在 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.pswp.cn/web/89556.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89556.shtml
英文地址,请注明出处:http://en.pswp.cn/web/89556.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云alicloud liunux3-安装docker

你这个错误&#xff1a;Curl error (35): SSL connect error for https://download.docker.com/linux/centos/8/x86_64/stable/... Error: Failed to download metadata for repo docker-ce-stable: Yum repo downloading error说明你的机器访问 download.docker.com 的 HTTPS …

【世纪龙科技】汽车故障诊断与排除仿真教学软件

在汽车产业智能化、电动化转型加速的今天&#xff0c;汽车维修行业对技术人才的要求已从传统经验型向“理论实践数字化”复合型转变。然而&#xff0c;实车实训成本高、安全隐患大、教学场景受限等问题&#xff0c;始终制约着职业教育的高质量发展。江苏世纪龙科技有限公司立足…

柴油机活塞cad【4张】三维图+设计说明书

1015柴油机活塞结构设计及温度场分析 摘 要 随着科研的进步&#xff0c;内燃机技术得到了快速的发展&#xff0c;低排放高效率的内燃机的发展成为内燃机发展的主要趋势&#xff0c;活塞作为内燃机的主要组成部件&#xff0c;在内燃机中扮演着至关重要的作用。活塞在内燃机中始终…

雪豹大模型驱动效率革命 华鼎冷链科技重构餐饮供应链神经网络

当餐饮行业的开店率高达67.5%、闭店率达61.2%时&#xff0c;供应链该如何进行革新与升级&#xff1f; 在郑州盛大启幕的第三届中国火锅烧烤领潮峰会上&#xff0c;华鼎冷链科技CEO王君以“AI驱动智慧供应链赋能餐饮行业新升级”为主题分享时称&#xff0c;当前餐饮行业高闭店率…

汽车功能安全 -- TC3xx外部看门狗

之前聊过TC3xx SMU关于内部看门狗&#xff08;CPU Watchdog 和Safety Watchdog&#xff09;Alarm的处理方法。 汽车功能安全--TC3xx SMU之看门狗alarm处理 在里面我们提到了这些Alarm关联的功能安全机制&#xff1a; SM[HW]:SCU:ENDINIT_WATCHDOG SM[HW]:SCU:SAFETY_WATCHD…

如何为“地方升学导向型”语校建模?Prompt 框架下的宇都宫日建工科专门学校解析(7 / 500)

如何为“地方升学导向型”语校建模&#xff1f;Prompt 框架下的宇都宫日建工科专门学校解析&#xff08;7 / 500&#xff09; 系列说明 500 所日本语言学校结构化建模实战&#xff0c;第 7 篇。每篇拆解 1 所学校在 Prompt-QA 系统中的建模策略&#xff0c;分享工程经验&#x…

Flutter 入门指南:从基础到实战

介绍 Flutter Flutter 是 Google 开发的开源移动应用软件开发工具包&#xff08;SDK&#xff09;&#xff0c;用于快速在 iOS 和 Android 上构建高质量的原生界面。Flutter 的一大特点是其跨平台功能&#xff0c;让开发者能够使用同一套代码基础为两个平台构建应用。这一点通过…

八字命理:枭印夺食的形成原理与解决办法

枭印夺食(|)含义:原局食神伤官为喜用&#xff0c;印为忌正印/偏印克制了食神/伤官&#xff0c;克制形式可以是盖头/截脚/同在天干或者地支时相克(2)表现症状:emo、敏感、好面子、不敢开口说话、被环境压制(3)症状剖析:印为忌&#xff1d;他人即地狱&#xff0c;不论正印(吉神)还…

数组和对象的深拷贝和浅拷贝的方法

数组和对象的深拷贝、浅拷贝方法有所不同&#xff0c;以下是常见的实现方式&#xff1a;一、浅拷贝方法&#xff08;数组和对象通用/专用&#xff09;浅拷贝只复制表层数据&#xff0c;嵌套的引用类型仍共享内存。1. 数组的浅拷贝- 扩展运算符&#xff08;...&#xff09;&…

【RK3576】【Android14】开发板概述

获取更多相关的【RK3576】【Android14】驱动开发&#xff0c;可收藏系列博文&#xff0c;持续更新中&#xff1a; 【RK3576】Android 14 驱动开发实战指南 1. 引言 RK3576处理器简介&#xff1a; RK3576 是一颗高性能、低功耗的应用处理器芯片&#xff0c;专为ARM PC、边缘计算…

凸优化课程学习笔记(一)

凸优化课程学习笔记(一) 课程:B站清华大学陈剑博士《凸优化基础理论与应用》 优化理论概述 1. 优化序论 定义:凸优化是一门应用极为广泛的学科,主要研究如何对决策问题进行最优选择,探讨最优解的性质,寻找高效的计算方法,并分析这些方法的理论基础与实际应用表现。…

(四)OpenCV——特征点检测与匹配

前言 特征点检测与匹配是计算机视觉中的基础技术&#xff0c;广泛应用于图像拼接、物体识别、三维重建、运动跟踪等领域。OpenCV 提供了多种特征检测与匹配算法的实现。 特征点检测与匹配是计算机视觉中的核心技术&#xff0c;广泛应用于多个领域。以下是其主要应用场景&…

if (a == 1 a == 2 a == 3)返回true的问题思考

引文&#xff1a; 无意中看到了这样的非常规逻辑&#xff0c;在想前后端应该都可以实现&#xff0c;a 是变量&#xff0c;或者操作a时触发了值得改变。 意义&#xff1a; 该问题让我们知道了一切规则都是可以被打破的&#xff0c;世界上的规则都是为了解释某种现象设计的。 题目…

MySQL的索引操作及底层结构浅析

一.索引提高数据库的性能&#xff0c;索引是物美价廉的东西了。不用加内存&#xff0c;不用改程序&#xff0c;不用调sql&#xff0c;只要执行正确的 create index &#xff0c;查询速度就可能提高成百上千倍。但是天下没有免费的午餐&#xff0c;查询速度的提高是以插入、更新…

stm32f4 dma的一些问题

文章目录前言一、使用开发板烧录dma代码不生效问题二、一个工程同时使用uart2、uart3借助dma来传递1.并行。2.DMA "同时工作"的本质3.总线访问的具体含义4.实际效果5.最佳实践5.1 总线传输机制&#xff1a;6.DMA传输中断的问题总结前言 记录一些使用stm32f4 dma过程…

登录功能实现深度解析:从会话管理到安全校验全流程指南

登录功能实现深度解析&#xff1a;从会话管理到安全校验全流程指南大家好&#xff0c;我是凯哥Java本文标签&#xff1a;登录验证流程、过滤器与拦截器、安全防护措施简介本文深入探讨了从登录功能实现到会话管理和安全校验的全流程&#xff0c;包括参数校验、身份验证、令牌生…

2023 年 5 月青少年软编等考 C 语言六级真题解析

目录 T1. 字符串插入 思路分析 T2. 机器翻译 思路分析 T3. 栈基本操作 思路分析 T4. 双端队列 思路分析 T1. 字符串插入 题目链接:SOJ D1138 有两个字符串 s t r str str 和 s u b s t r substr substr, s t r str str 的字符个数不超过 10 10 10, s u b s t r substr …

Redux架构解析:状态管理的核心原理

Redux 作为 JavaScript 应用的状态管理库&#xff0c;其技术架构与核心原理围绕​​可预测的状态管理​​设计&#xff0c;通过严格的单向数据流和函数式编程理念实现复杂应用的状态控制。以下从设计理念、核心架构、工作流程、源码实现等角度进行系统性剖析&#xff1a;一、设…

linux制作镜像、压缩镜像、烧录的方法

最近在玩香橙派的时候&#xff0c;需要搞多个板子&#xff0c;一个一个配环境也太麻烦了吧......于是通过搜索&#xff0c;发现可以把linux设备&#xff08;比如香橙派&#xff0c;树莓派等等&#xff09;制作为镜像&#xff0c;然后像烧录官方镜像一样烧进新的sd卡&#xff0c…

机械材料计算软件,快速核算重量

软件介绍 今天为大家推荐一款专为机械行业设计人员打造的金属材料重量计算软件&#xff0c;帮助工程师快速完成材料重量核算。 软件特点 这款绿色版计算工具体积小巧&#xff0c;不足100KB&#xff0c;无需安装即可直接运行&#xff0c;不占用系统资源&#xff0c;特别适…