JavaWeb-Cookie与Session

一、概念

是否还记得我们在HTTP概念中提到:HTTP的一大特点是无状态,这意味着多次HTTP请求之间是无法共享数据的。而在请求之间共享一些数据又是我们期望达到的效果。(例如登录的记住我功能)于是便有了会话跟踪技术,而Cookie与Session就是两种实现方式。

二、Cookie

Cookie:客户端会话跟踪技术,客户端第一次请求服务端时,服务端会生成一个Cookie,并返回给客户端。此Cookie会保存在客户端,并且在以后每次请求中都携带Cookie访问服务端。

(1) 服务端生成Cookie并返回给客户端
package com.byhuang.cookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("name", "value");
        resp.addCookie(cookie);
    }
}
(2)再次请求服务端时,将携带Cookie访问。在服务端接收Cookie:
package com.byhuang.cookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/bServlet")
public class BServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies) {
            if ("name".equals(cookie.getName())) {
                System.out.println("here:" + cookie.getName() + cookie.getValue());
            }
        }
    }
}
(3) 原理

Cookie的实现是基于HTTP协议的。Web服务器中会在响应头里设置setCookie字段,值为key=value。在上面的例子中,就是setCookie: name=value;当客户端下次请求服务端时,会在请求头中添加Cookie字段,值为所有Cookie的键值对,并用分号分割。如下图所示:

(4) Cookie使用细节

默认情况下,Cookie存储在浏览器的内存中,会随着浏览器的关闭而销毁。但是例如记住我这种功能,不可能要求用户的浏览器保持不关闭。相关API给我们提供了方法:

setMaxAge(int seconds): 参数表示让这个Cookie的存活时间(单位秒),即使关闭浏览器,也会持久化存储在硬盘中,下次打开浏览器Cookie依然是有效的。参数为0表示立即删除这个Cookie,Cookie为负数表示在当前浏览器的内存中,当浏览器关闭时,则Cookie自动销毁,这也是Cookie的默认状态。

三、Session

Session:服务端会话跟踪技术:将数据保存在服务端。Java提供了HttpSession接口,来实现一次会话的多次请求之间的数据共享。

(1) 服务端生成session
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("/asession")
public class ASession extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        System.out.println(session);
        session.setAttribute("user", "zs");
    }
}
(2)客户端在同一个会话中再次请求服务端时,可以取到同一个session,并取到在上一次请求传递的值。
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("/bsession")
public class BSession extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        System.out.println(session); // 打印的Seesion与第一次请求时打印的相同
        String username = (String) session.getAttribute("user");
        System.out.println(username);  // 取出第一次请求时设置的值,实现了会话间数据共享
    }
}
(3)原理

Session是基于Cookie实现。Web服务器(如Tomcat)会自动把session id以Cookie的形式发送给客户端,客户端在下次请求时,会携带该session id访问。于是在下次获取session时,可以根据这一session id找到在上一次访问的HttpSession对象。而其它客户端的session id与该id不同,于是就实现了在同一会话中,通过session共享数据的目的。

(4) session的使用细节

session的钝化、活化:我们上面提到session是存储在服务端的,也就是session存储在服务器的内存中的。那么在服务器重启后,内存被销毁,session就消失了。但是session有钝化机制,也就是说,当服务器正常关闭时,还存活着的session(在设置时间内没有销毁) 会随着服务器的关闭被以文件(“SESSIONS.ser”)的形式存储在tomcat 的work 目录下,这个过程叫做Session 的钝化。而活化是指重启服务器后,从文件中加载数据到session中。

session的销毁:我们日常生活中也有登出的功能,这里就需要用到session的销毁机制。可以用session.invalidate()方法来实现,读者可自由尝试,笔者在这里不再提供演示。

四、cookie与session的对比
  1. 存储位置:cookie是存储在客户端,session是存储在服务端
  2. 安全性:由于存储位置的区别,因此cookie更不安全
  3. 数据大小:cookie最大是3KB,session无大小限制
  4. 存储时间:cookie可以长期存储,session默认30分钟
  5. 服务器性能:由于session存储在服务端,所以会占用服务器资源

根据以上的对比,我们来看以下几个场景,我们应该使用cookie还是session呢(重要)

(1)早期购物网站的购物车,是在登录前也可以加入商品的。在下次进入网站时,此前加入的商品依然可以显示出来。

分析:这个场景下,肯定是要求客户端被关闭后,再次打开时依然能够取到数据。那这样的话session就不能满足了,因为session id作为cookie存储在客户端,会随着客户端的关闭而销毁(session id通常不会持久化在硬盘中);因此会使用cookie将购物车里的数据持久到本地的硬盘里,下次打开时重新加载进浏览器中。有读者可能会有疑问,session id不是cookie吗,不能把这个cookie的过期时间设置的久一些,然后持久化在客户端中吗?要知道,session id作为cookie是Web服务器(如Tomcat)替我们完成的,我们不能简便去修改这个动作。当然我们也可以在Web项目中设置全局的session的过期时间,但是这似乎会影响到其它功能,比如说下面第(2)个场景。因此,还是需要使用cookie,而非去修改session的默认超时时间。多说一句,现在购物车的功能大多都修改为存储在数据库中,这也就意味着在登录前取消了加入购物车的这一功能。

(2)登录成功之后的用户数据

分析:由于cookie需要频繁地在客户端与服务端传递,显然是不安全的,而用户信息显然是敏感数据,毫无疑问,这个场景需要使用session。

(3)记住我功能

分析:这个也是需要关闭浏览器再重新打开后依然生效的,因此也需要保存在cookie中。但是这个也需要传递用户数据,因此强行实现这个功能是不安全的,所以目前许多网站都逐渐取消了这人曾经风靡一时的功能。

(4)图片验证码,在注册或登录时,常常会遇到输入完用户名和密码后填写一个图形验证码的场景,比如需要输入图片中的几个数字。

分析:使用图片验证码正是为了有人恶意攻击,比如暴力尝试密码、暴力注册大量用户攻击服务器数据库等。如果使用cookie,相当于把答案传递给了客户端,所以“答案”(数据)只能保存在服务端,使用session。

以上便是对cookie和session的介绍,接下来,笔者将会用本篇的知识来实现一个用户登录、注册、记住我、验证码的小demo,请读者继续关注。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/336260.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt拖拽组件与键盘事件

1.相关说明 1.设置widget或view的拖拽和放置模式函数setDragDropMode参数说明,NoDragDrop(无拖拽和放置)、DragOnly(只允许拖拽)、DropOnly(只允许放置)、DragDrop(允许拖拽和放置)、InternalMove(只移动不复制) 2.设置widget或view的放置动作函数setDefaultDropAct…

python 实现大语言模型中的概率论:两人轮流出手对决时取胜概率的推导

假设你跟朋友通过打赌投篮来打赌一万块。你们找到一个篮球框,然后约定轮流投篮,谁先投进谁赢。假设你投进的概率是 p,也就是投不进的概率是 1-p,你对手投进的概率是 q,投不进的概率是 1-q,如果由你先投,那么…

反序列化提升刷题(2)

今天的例题&#xff1a; <?phphighlight_file(__FILE__);class ctfshowvip{public $username;public $password;public $code;public function __construct($u,$p){$this->username$u;$this->password$p;}public function __wakeup(){if($this->username! || $thi…

解决 vue 项目开发越久 node_modules包越大的问题

解决 vue 项目开发越久 node_modules包越大的问题 node_modules.cache 文件&#xff08;编译缓存文件 可以删除 &#xff09; compression-webpack-plugin 禁止缓存 const CompressionPlugin require("compression-webpack-plugin");module.exports {plugins: [ne…

面向对象之深度优先和广度优先

面向对象深度优先和广度优先是什么&#xff1f; 二叉树的两种遍历是数据结构的经典考察题目, 广度遍历考察队列结构, 深度遍历考察递归 深度优先 先序遍历(父, 左子, 右子) 0, 1, 3, 7, 8, 4, 9, 2, 5, 6 中序遍历(左子, 父, 右子) 7, 3, 8, 1, 9, 4, 0, 5, 2, 6 后序遍历(左子…

SpringBoot跨域问题解决

前端访问后台接口时&#xff0c;浏览器报错&#xff0c;跨域无法访问。 报错信息如下&#xff1a; Response to preflight request doesnt pass access control check: No Access-Control-Allow-Origin header is present on the requested resource. 经过一番百度之后&#…

【JVM】运行时数据区

文章目录 运行时数据区程序计数器栈栈帧 堆方法区本地方法栈直接内存变量存储位置 面试题本地方法栈有什么用&#xff1f;没有程序计数器会怎么样&#xff1f;说一说Java的内存分布情况类存放在哪里&#xff1f;局部变量存放在哪里&#xff1f; 运行时数据区 java虚拟机在运行…

acwing讲解篇之93. 递归实现组合型枚举

文章目录 题目描述题解思路题解代码 题目描述 题解思路 本题相当于二叉树的深度优先遍历&#xff0c;树的第i层表示第i个数选或不选&#xff0c;当选择了m次左节点后退出 我们记录当前递归的深度deep 然后用state进行状态压缩&#xff0c;state第i位是1表示选第i个数&#xff…

FaFu--练习复盘--2

3、函数练习 3.1、函数表达式&#xff08;1&#xff09; 描述 根据以下公式计算数学表达式的值&#xff0c;并将结果作为函数值返回。在main()函数中输入x&#xff0c;调用函数fun(x)&#xff0c;并输出fun(x)的值。 输入 输入1行&#xff0c;包含1个double类型的浮点数&…

git22端口超时

笔记本换了个主板后&#xff0c;将内容用git上传到GitHub时发现22端口超时。 以为是网络啥的原因&#xff0c;但是用ssh -T gitgithub.com进行多次测试&#xff0c;发现不是网络问题。按照网上操作&#xff0c;在.ssh文件夹内将config文件进行修改&#xff0c;改成&#xff1a;…

python爬取图片(thumbURL和html文件标签分别爬取)

当查看源代码&#xff0c;发现网址在thumbURL之后时&#xff0c;用此代码: # 当查看源代码&#xff0c;发现网址在thumbURL之后时&#xff0c;用此代码:import requestsheaders {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121…

cs231n assignment1——SVM

整体思路 加载CIFAR-10数据集并展示部分数据数据图像归一化&#xff0c;减去均值&#xff08;也可以再除以方差&#xff09;svm_loss_naive和svm_loss_vectorized计算hinge损失&#xff0c;用拉格朗日法列hinge损失函数利用随机梯度下降法优化SVM在训练集和验证集计算准确率&a…

vue项目执行依赖安装(npm i或npm install )报ls-remote -h -t异常

从git拉取的vue项目执行依赖安装时一直报错&#xff0c; 报错如下图&#xff1a;首先&#xff0c;查看了node版本、npm配置的镜像地址均没找到解决办法。 在命令行中直接输入git发现提示于是从网上搜到了一个博文https://blog.csdn.net/weixin_49159364/article/details/118198…

【LeetCode】141. 环形链表

leetcode题目链接 141. 环形链表 #include <stdio.h> #include <stdbool.h>struct ListNode {int val;struct ListNode* next; }; typedef struct ListNode ListNode;bool hasCycle(ListNode* head) {ListNode* slow head, * fast head;while (fast &&…

2023年上半年网络工程师真题(1/3)

1.固态硬盘的存储介质是&#xff08;B&#xff09;。 A.光盘 B.闪存 C.软盘 D.磁盘 SSD存储介质是FLASH(一块块的存储芯片)&#xff0c;HDD(机械硬盘)存储介质是磁盘(机械臂和盘道)&#xff0c;补充:U盘的存储介质也是FLASH闪存。 2.虚拟存储技术把&#xff08;A&#xf…

最长公共前缀(Leetcode14)

例题&#xff1a; 分析&#xff1a; 我们可以先定义两个变量 i &#xff0c; j&#xff0c; j表示数组中的每一个字符串&#xff0c; i 表示每个字符串中的第几个字符。一列一列地进行比较&#xff0c;先比较第一列的字符&#xff0c;若都相同&#xff0c;则 i &#xff0c;继…

可视化 | 【echarts】渐变条形+折线复合图

文章目录 &#x1f4da;html css&#x1f4da;js&#x1f407;总体框架&#x1f407;option配置项 &#x1f4da;html css html&#xff1a;在这主要是用于整合&#xff0c;将html、css、js连接在一块&#xff0c;虽然单个模板代码量不大&#xff0c;但还是先分开&#xff0…

AI语音合成工具-Lalamu Studio

近期&#xff0c;Lalamu Studio开启了beta版本测试&#xff1a;Lalamu Studio。该工具整合了TTS和lip sync功能&#xff0c;可以让任意视频中的人物开口说话&#xff0c;并精确模拟口型。 例如&#xff0c;选择一段视频素材&#xff0c;添加由Ai合成的语音&#xff0c;即可完成…

MyBatis 系列:MyBatis 源码环境搭建

文章目录 一、环境准备二、下载 MyBatis 源码和 MyBatis-Parent 源码三、创建空项目、导入项目四、编译 mybatis-parent五、编译 mybatis六、测试总结 一、环境准备 jdk&#xff1a;17 maven&#xff1a;3.9.5 二、下载 MyBatis 源码和 MyBatis-Parent 源码 Mybatis&#x…

求职中遇到的性格测试

怎样才能不被刷? 最主要的就是自己的性格特征跟当前应聘的岗位是否相符合&#xff0c;这个符合程度越高&#xff0c;通过率自然也就越高。正规的做法都有一个岗位模型&#xff0c;也叫岗位胜任力模型。 以大五人格测试为例&#xff0c;完整版包含30个性格维度&#xff0c;从…