HTTP中的Cookie、Set-Cookie

article/2025/9/29 3:42:42

请求头Cookie、响应头Set-Cookie

但是,我们又需要在不同请求-响应之间,来区分请求-响应是不是同一个用户发起的。


比如:用户购买越多,折扣越多的活动,就需要我们分辨出不同请求-响应之间的逻辑关系

    // 专门用来发凭证(cookie)的@GetMapping("/set-cookie")public void setCookie(HttpServletRequest request, HttpServletResponse response) throws Exception {// servlet 里的处理方式// 不要用中文,因为 cookie 的设置和携带是放在请求响应头中的,字符集编码是西文格式,不支持中文Cookie cookie1 = new Cookie("name", "chen");Cookie cookie2 = new Cookie("learning", "java");Cookie cookie3 = new Cookie("time", "2022");response.addCookie(cookie1);response.addCookie(cookie2);response.addCookie(cookie3);// 设置响应体的字符集编码response.setCharacterEncoding("utf-8");// 设置响应体的格式 —— 纯文本response.setContentType("text/plain");// 写响应内容response.getWriter().println("cookie 设置成功,请观察开发者工具的 网络面板 和 应用面板");}// 记录用户访问次数private final Map<String, Integer> countMap = new HashMap<>();  // 这个 map 就是就是房子private final Map<String, Map<String, Object>> 模拟session的结构 = new HashMap<>();// 模拟一个 session@GetMapping("/use-cookie")public void useCookie(HttpServletRequest request, HttpServletResponse response) throws Exception {String id = null;Cookie[] cookies = request.getCookies();if (cookies != null) {for (Cookie cookie : cookies) {if (cookie.getName().equals("id")) {id = cookie.getValue();}}}Integer count = null;if (id == null) {// cookie 中没有携带 id,认为是用户第一次访问// 将当前时间戳当作这次用户的访问标识long ts = System.currentTimeMillis();System.out.println("是第一次访问");id = String.valueOf(ts);Cookie cookie = new Cookie("id", id);response.addCookie(cookie);count = 1;countMap.put(id, count);} else {// cookie 中携带了 id,说明之前是访问过的System.out.println("不是第一次访问");count = countMap.get(id);if (count == null) {// 由于程序重启,内存中的 countMap 的数据丢了// 所以当成第一次吧count = 1;} else {count += 1;}countMap.put(id, count);}System.out.println("现在统计的所有人的访问次数:");for (Map.Entry<String, Integer> entry : countMap.entrySet()) {System.out.printf("%s => %d\r\n", entry.getKey(), entry.getValue());}// 设置响应体的字符集编码response.setCharacterEncoding("utf-8");// 设置响应体的格式 —— 纯文本response.setContentType("text/plain");// 写响应内容if (count == 1) {response.getWriter().println("第 1 次访问,您的 id 是: " + id);} else {response.getWriter().printf("欢迎 %s 的第 %d 次访问\r\n", id, count);}}

Session会话

 

Session是保存在服务器的,专属某次会话的,一组数据。可以跨请求访问到(生命周期是跨请求存在的)。通常: Session 中保存的数据也可以视为name-value
一般利用Cookie设置session-id,这样,客户端和服务器之间仍然使用cookie机制,只是cookie 只传递id即可。主要数据全部保存在服务器。

Cookie和Session在实际场景应用

Cookie和Session在实际场景中最常见的应用——在线用户管理(如何在一次HTTP请求-响应中判断用户是否登录,以及登录用户是谁)
用户管理:用户注册(建档)、用户登录(当前用户在线)、用户退出(当前用户下线)、用户注销(销档)、
获取当前登录用户(currentUser):判断用户是否在线;如果在线,得到当前用户是谁。

和Cookie、Session有关系的,其实是在线用户状态的维护:用户登录、用户退出、获取当前登录用户信息;当前用户保存Session中。

用户注册:为用户建档,为用户信息做持久化保存——在数据库中维护一条用户信息,
记录用户基本信息。用户登录时通过验证这份基本信息来证明“你”是“你”

用户名+密码的方案——设计一个最简单的数据库表:
用户表(users)

{该用户的唯一标识符(uid) 、

该用户的用名——登录时唯一验证,需要保持记录的唯一性(username)、

密码(暂时明文)}

用户注册示例

数据库准备

 

注册场景

    // 1. 支持 POST// 2. 资源路径是 /register.do@PostMapping("/register.do")// 3. 希望结果是重定向,所以,不需要使用 @ResponseBody 注解修饰方法// 4. 方法的返回值类型是 String,到时候会返回 "redirect:..."// 5. 需要读取用户提交的 <input type="text" name="username" placeholder="用户名"> 和 <input type="text" name="password" placeholder="密码">// 5. 所以,方法的形参有两个,分别使用 @RequestParam 修饰public String register(@RequestParam("username") String username, @RequestParam("password") String password) {System.out.println("用户注册:username = " + username + ", password = " + password);// 1. TODO: 本来应该要去完成的参数合法性校验// 2. 执行 SQL 语句String sql = "insert into users (username, password) values (?, ?)";try (Connection c = DBUtil.connection()) {try (PreparedStatement ps = c.prepareStatement(sql)) {ps.setString(1, username);ps.setString(2, password);ps.executeUpdate();}} catch (SQLException exc) {System.out.println("用户注册失败");exc.printStackTrace(System.out);return "redirect:/register.html";   // 失败后重定向到 注册页}System.out.println("用户注册成功");return "redirect:/login.html";    // 目前用户最终看到 404}

登录场景

    // 准备 POST /login.do 动态资源@PostMapping("/login.do")// 要重定向,不需要 @ResponseBody 注解修饰方法// 返回值类型是 String// 要读取用户输入的用户名 + 密码信息,和注册一样// 要创建 session 对象,所以,形参中有 HttpServletRequest requestpublic String login(@RequestParam("username") String usernameInput,@RequestParam("password") String passwordInput,HttpServletRequest request) {System.out.println("用户登录:username = " + usernameInput + ", password = " + passwordInput);// TODO: 参数合法性校验// 通过数据库查询该用户的信息
//        Integer uid = null;     // 使用 Integer 而不是 int,是 Integer 可以保存 null 这种特殊值
//        String username = null;
//        String password = null;User user = null;try (Connection c = DBUtil.connection()) {String sql = "select uid, username, password from users where username = ? and password = ?";try (PreparedStatement ps = c.prepareStatement(sql)) {ps.setString(1, usernameInput); // 把用户填写的用户名添加到 SQL 参数ps.setString(2, passwordInput); // 同理,密码// 带结果的,并且结果只有 1 条 或者 0 条try (ResultSet rs = ps.executeQuery()) {if (rs.next()) {// 查询到了 1 条记录,说明用户名 + 密码正确int uid = rs.getInt("uid");String username = rs.getString("username");    // 实际上,这两个字段可以不查询String password = rs.getString("password");    // 实际上,这两个字段可以不查询user = new User(uid, username, password);} else {// 一条记录都没有查询到,这里什么都不干// 这里加上 else 的目的是为了写这个注释,以后我就不写了}}}} catch (SQLException exc) {System.out.println("登录失败 by 数据库 SQL 执行失败,如果符合 HTTP 语义,应该是 500 错误");exc.printStackTrace(System.out);return "redirect:/login.html";}// 根据 uid 或者 username 或者 password 值来判断用户是否登录成功了,其中一个就行了if (user == null) {// 登录失败了System.out.println("登录失败 by 用户输入的参数有错误,如果符合 HTTP 语义,应该是 4XX 错误");return "redirect:/login.html";}// 登录成功// 获取 session 对象HttpSession session = request.getSession(); // 不带参数,默认是 create = true// 由于之前很大可能是没有 session 的// 所以内部所作的工作是// 1. 创建一个随机的 <session-id>// 2. 为这个 <session-id> 分配一个 HttpSession 对象(Map<String, Object> 结构)// 3. 响应中设置 Cookie(Set-Cookie):JSESSIONID=<session-id>// 4. 所以,应该能在前端看到浏览器中有个 JSESSIONID 的 cookie// 把当前用户的信息(uid、username、password)保存到 session 中,key 我们随意指定// currentUser.uid、currentUser.username、currentUser.password
//        session.setAttribute("currentUser.uid", uid);
//        session.setAttribute("currentUser.username", username);
//        session.setAttribute("currentUser.password", password);session.setAttribute("currentUser", user);System.out.println("登录成功");return "redirect:/";    // 404}

    // GET /@GetMapping("/")// 在响应体中输入内容,所以 @ResponseBody 注解修饰方法 + 方法返回值类型是 String// 响应的 Content-Type 是 HTML,返回值直接当成 HTML 内容在对待// 由于需要获取 HttpSession 对象,所以,形参中有 HttpServletRequest request@ResponseBodypublic String getCurrentUser(HttpServletRequest request) {
//        Integer uid = null;
//        String username = null;
//        String password = null;User currentUser = null;HttpSession session = request.getSession(false);if (session != null) {System.out.println("有 session 对象");// 说明是有 Session 的// 获取的时候,必须保证 key 和 登录场景下 setAttribute 时的 key 一致// getAttribute(...) 的返回值类型是 Object// Object 是 Integer 的上级类型// Object -> Integer 是向下转型// 向下转型是不自然的,是有风险的,所以程序员(我们)明确告诉编译器是我要转的,职责我承担(有异常我自己弄)// 需要通过类型强制转换 (Integer)
//            uid = (Integer) session.getAttribute("currentUser.uid");
//            username = (String) session.getAttribute("currentUser.username");
//            password = (String) session.getAttribute("currentUser.password");currentUser = (User) session.getAttribute("currentUser");// 如果当时没有设置,getAttribute 的返回值是 null} else {System.out.println("没有 session 对象");// 反之没有 session,什么都不需要做}if (currentUser == null) {System.out.println("没有拿到 uid");// session 可能是 null 或者 session.getAttribute("currentUser.uid") 是 null// 不管是哪种可能,都代表本次请求-响应的用户,没有经历过登录的流程,也就是用户未登录return "用户未登录,请到 <a href='/login.html'>登录页</a> 进行登录";} else {System.out.println("拿到 uid 了");
//            return String.format("当前登录用户为: uid = %d, username = %s, password = %s", uid, username, password);return String.format("当前登录用户为: %s", currentUser);   // 这里虽然没写,但实际就是调用的 currnetUser.toString()}}

用户退出


http://chatgpt.dhexx.cn/article/over2itv.shtml

相关文章

php 中cookie的简介,setcookile() 的用法,如何理解cookie

最近心里想着学更新的技术&#xff0c; 了解更多的框框。但是回过头来&#xff0c;我想学一下最基础的东西&#xff0c;因为&#xff0c;一路走来&#xff0c; 技术都是自学来的&#xff0c;肯定还有很多瑕疵的&#xff0c; 比如&#xff0c; 什么是http协议&#xff0c;虽然是…

cookie和set-cookie的区别及token值

什么是cookie cookie是一段文本,格式key-value cookie鉴权原理 1.当客户端第一次访问服务器端时,服务器会成cookie信息,并且在响应头的set-cookie里面把生成的cookie信息发送给客户端 2.当客户端第2-N次访问服务端的时候,那么客户端就会在请求头的cookie带上cookie信息,从而实现…

数学物理方法 高教 第四版 课后习题答案

数学物理方法 高等教育出版社 第四版 课后习题答案 课后习题答案下载地址 链接&#xff1a;https://pan.baidu.com/s/1KqePoJ8AXb4vAxXadOCfCg 提取码&#xff1a;73um 如果链接失效扫一扫右侧&#xff0c;回复 数学物理方法答案 即可免费获取 百度文库所有文档原格式下载方法…

四年级计算机上册说课ppt,四年级上册《画长方形》说课稿

四年级上册《画长方形》说课稿 《画长方形》是20**年经过教育部审定的人教版《义务教育教科书》四年级上册第五单元《平行四边形和梯形》第4课时的内容&#xff0c;我将从教材解读和教学实施两部分进行说课。 一、教材解读 本节课是人教版小学数学四年级上册第5单元《平行四边形…

python编程 上册第4版_统编版四年级语文上册第1课观潮视频+课件+练习

文末有打印资料的方法 往期回顾&#xff1a; 2020秋部编版四年级上册语文教材解析(附各单元分析)&#xff0c;可下载&#xff01; 【暑假预习 】 部编版语文四年级上册课堂笔记 部编版四年级语文上册1~8单元知识梳理&#xff0c;可下载预习&#xff01; 2020秋人教版四年级上册…

高等数学(第七版)同济大学 总习题二 个人解答

高等数学&#xff08;第七版&#xff09;同济大学 总习题二 1. 在“充分”“必要”和“充分必要”三者中选择一个正确的填入下列空格内&#xff1a; \begin{aligned}&1. \ 在“充分”“必要”和“充分必要”三者中选择一个正确的填入下列空格内&#xff1a;&\end{align…

数学第一单元计算机思维导图,七年级下册数学第一单元思维导图

提到下册,大家应该都不陌生,有人问数学四年级下册第一单元测试卷,还有人想问七年级下册数学整式的乘,这到底怎么回事呢?实际上七年级数学丰富的图形呢,今天小编就与大家分享七年级下册数学第一单元思维导图,欢迎大家参考和学习。 七年级下册数学第一单元思维导图 七年级…

同济大学高等数学上册第四章不定积分以及每日一题

第四章、不定积分 知识逻辑结构图 考研考试内容 原函数和不定积分的概念&#xff08;被积函数的要求、连续只是原函数存在的充分条件&#xff09;&#xff0c;不定积分的基本性质&#xff08;线性、和差与求导互逆&#xff09;&#xff0c;基本积分公式&#xff0c;不定积分的…

冀教版三年级计算机教学计划,冀教版数学小学三年级上册教学计划

冀教版数学小学三年级上册教学计划 篇一 一、本学期教学的 目的&#xff0c;任务与具体要求&#xff1a; (1) 本学期教学的目的 1 、认识生活中的大数&#xff0c;正确读写出中间或末尾有 0 的四位数&#xff0c;并会比较四位数的大小。 2 、会计算两、三位数乘一位数&#xff…

七年级上册数学计算机教学视频,人教版初中数学七年级上册

目录&#xff1a; 1.2  有理数 1.3  有理数的加减法 实验与探究  填幻方 阅读与思考  中国人最先使用负数 1.4  有理数的乘除法 观察与猜想  翻牌游戏中的数学道理 1.5  有理数的乘方 数学活动 小结 复习题1 第二章  整式的加减 2.1  整式 阅读与思考  数字1与字母X的…

四年级计算机上册课程标准,新课程标准人教版四年级上册数学全册教案设计

一、教学目的任务&#xff1a; (思想教育、“双基”教学、能力培养、智力开发、方法指导、习惯产生及培优、促中、转差的目标) 这一册教材的课堂目标是&#xff0c;让学员自主研究、合作&#xff0c;从而让学生&#xff1a; 1&#xff0e;认识计数单位“十万”“百万”“千万”…

四年级上册数学计算机笔记,读书笔记:最新人教版四年级上册数学总复习讲义...

四年级上册 教学重点&#xff1a;掌握制作统计图的方式跟方法。 教学难点&#xff1a;准确客观地体现统计数据。 教学过程&#xff1a; 一、复习指导 (1)什么是复式条形统计图&#xff1f;它与单式条形统计图有哪些区别与联系&#xff1f; (2)怎样制作复式条形统计图&#xff1…

小学数学四年级上册计算机教案,新人教版四年级上册数学教案

新人教版四年级上册数学教案 一、学生基本情况分析 经过三年级下学期的学习&#xff0c;学生的思维已经开始由具体形象思维过渡到抽象思维&#xff0c;对周围事物的认识较以前上升了一个层次&#xff0c;已经会用归纳概括的方法认识事物及解决问题&#xff0c;学生已经具备了初…

3.样条曲线之B样条曲线

B样条曲线 B样条是使用更广泛的逼近样条类。B样条有两个贝塞尔样条所不具备的优点&#xff1a;1、B样条多项式次数可独立于控制点数目&#xff08;有一定限制&#xff09;&#xff1b;2、B样条允许局部控制曲线或曲面。缺点是B样条比贝塞尔样条更复杂。我们可以把沿B样条曲线的…

曲线理论-详解Bezier曲线、B样条曲线、NURBS曲线

文章目录 曲线理论-详解Bezier曲线、B样条曲线、NURBS曲线样条曲线Bezier曲线&#xff0c;B样条曲线 &#xff0c;NURBS曲线Bezier曲线B样条曲线参考内容 曲线理论-详解Bezier曲线、B样条曲线、NURBS曲线 一直使用三维软件绘制曲线曲面&#xff0c;然而对曲线曲面的基本理论并…

样条曲线(参数曲线)曲率

曲率计算公式 设参数曲线C(u): C ( u ) ( x ( u ) , y ( y ) , z ( u ) ) C(u) (x(u),y(y),z(u)) C(u)(x(u),y(y),z(u)) 曲线曲率表达为&#xff1a; k ( u ) ∣ C ′ ( u ) C ′ ′ ( u ) ∣ ∣ C ′ ( u ) ∣ 3 ( 1 ) k(u)\frac{|C^{}(u)\times C^{}(u)|}{|C^{}(u)|^…

计算机图形学-样条曲线Spline

内容来自《计算机图形学》第四版 第14章-样条表示 目录 [1] 样条的种类1. 插值样条2. 逼近样条 [2] 参数连续性条件[2] 几何连续性条件[3] 样条描述1. 列出一组施加在样条上的边界条件2. 列出描述样条特征的行列式3. 列出一组混合函数或基函数 [4] 三次样条插值方法1. 自然三次…

样条曲线(spline)

文章目录 样条&#xff08;spline&#xff09;是什么&#xff1f;样条曲线的定义样条曲线的分类B-splineDefinitionPropertyB-spline vs. Bzier curveHow can we prove that a Bezier curve is a specific case of a B-spline curve by the definition of B-splines? Bzier sp…

样条曲线

基本概念 在计算机图形中&#xff0c;样条曲线&#xff08;spline curve&#xff09;指由多项式曲线段连接而成的曲线&#xff0c;在每段的边界处满足特定的连续性条件。样条曲面&#xff08;spline surface&#xff09;可以使用两组样条曲线进行描述。 给定一组称为控…

布丁压缩注册表删除路径

被布丁压缩的弹窗广告烦了好几天&#xff0c;卸载了好几次又自动安装了&#xff0c;今天终于忍无可忍&#xff0c;所以今天必须得跟它say Byebye&#xff01; winR快捷键&#xff0c;输入regedit&#xff0c;打开注册表 路径在这里 找注册表里的文件删除就ok 保险起见 在C:\Pr…