用户状态保持机制-Session

0、业务需求


会话:web应用中的会话是指一个客户端浏览器和服务器之间连续发生的一系列请求和响应的过程。
会话状态:web应用中的会话状态是指web服务器与浏览器在会话过程中产生的状态信息,借助会话状态,服务器能够把属于同一会话中的一系列的请求和响应过程关联起来。

Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种状态保持机制。

Web应用开发中,存储和管理用户状态是至关重要的。为了实现这一目标,开发者通常依赖于两种主要机制:Cookie和Session。尽管它们都是为了维护用户状态而设计的,但它们在实现方式、安全性、存储位置和容量等方面存在一些显著的区别。

Cookie存储在浏览器中,可以设置过期时间,而Session存储在服务器端,关闭浏览器后自动失效。Session相对于Cookie更安全,但仍然存在安全风险。Session可以存储任意类型的数据,而Cookie有大小限制。选择Session或Cookie应考虑应用场景和安全性要求。

咱们接着聊一下Session。

一、什么是Session

Session 是 Web 开发中常用的一种服务器端状态管理机制,它用于在服务器端存储用户的会话信息,以实现跨页面和跨请求的数据共享

二、Session的实现原理

存储在服务器端。当用户访问网站时,服务器会为该用户创建一个唯一的Session ID,并将其发送给用户的浏览器。浏览器将这个Session ID存储在Cookie中(注意这里的Cookie仅用于存储Session ID,而非用户信息)。之后,每当用户与服务器进行交互时,浏览器都会将这个Session ID发送给服务器。服务器根据这个Session ID查找对应的Session数据,从而识别用户并提供服务。

三、Session的优点

在安全性方面,Session相对于Cookie更为安全。由于Cookie存储在客户端的浏览器中,因此容易受到跨站脚本攻击(XSS)等安全威胁。攻击者可以通过窃取或篡改Cookie中的信息来冒充用户或窃取用户的敏感信息。而Session数据存储在服务器端,相对较难被攻击者直接访问或篡改。当然,这并不意味着Session就完全没有安全风险。如果服务器的安全措施不到位,或者存在其他漏洞,攻击者仍然有可能通过其他途径获取到Session数据。

四、Session的限制

然而,Session也有一些潜在的缺点。首先,由于Session数据存储在服务器端,因此需要额外的资源来管理和维护这些会话。这可能会增加服务器的内存消耗和复杂性。其次,Session通常具有较短的超时时间,这是为了防止服务器资源被长时间占用。这意味着如果用户在一个会话期间长时间没有活动,他们的会话可能会自动失效,从而导致他们需要重新进行身份验证或重新开始他们的会话。最后,Session通常是域特定的,这意味着它们通常只能在创建它们的同一Web域内有效。这使得跨域Session共享变得更加复杂和具有挑战性。

五、Session什么时候被创建

一个常见的错误是以为session在有客户端访问时就被创建,然而事实是直到某server端程序(如Servlet)调用HttpServletRequest.getSession(true)这样的语句时才会被创建

六、Session什么时候被删除

session在下列情况下被删除:
A.程序调用HttpSession.invalidate()
B.距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间
C.服务器进程被停止
再次注意关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象失效。

七、浏览器禁用Cookie怎么存储Sessionid?

前面红色字体讲到服务器创建sessionid后发送给浏览器,浏览器保存在cookie中,如果浏览器cookie被禁用该怎么办呢?必须有其它的机制以便在cookie被禁止时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终 保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。

八、简单示例

目标:

首先,创一个登录页面login.html,通过post方法提交到loginservlet。

然后,在loginservelt里面进行验证,验证通过则显示登录成功,并在后面添加一个logout链接,该链接指向另外一个logoutservlet,因为通过链接跳转过去的,所以请求出发logoutservlet中的doget方法。

最后我们写一个退出的logoutservlet,该servlet销毁session,使得其不再保存session,验证退出后能否直接登录。

1、新建login.html

添加如下代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
    <form action="LoginServlet" method="post">
      <table>
          <tr>
              <td>用户名:</td>
              <td><input type="text" name="username"></td>
          </tr>
          <tr>
              <td>密码:</td>
              <td><input type="password" name="password"></td>
          </tr>
          <tr><td>自动登录:<input type="checkbox" name="checkbox1"></td><td><input type="submit" value="登录"></td></tr>
      </table>
    </form>
</body>
</html>

2、新建LoginServlet

熟悉我内容的朋友,前面应该看到了创建过一个loginservlet的java程序,现在我就不新建了,直接修改那个文件,修改doPost方法。

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
        //设置参数解析编码格式
        String username = request.getParameter("username");
        String password = request.getParameter("password");
//        获取页面自动登录框的值
        String checkbox1 = request.getParameter("checkbox1");
        String jsessionid = null;
        HttpSession session = null;
        Cookie cookie;
//   先判断是否有cookies
        Cookie[] cookies = request.getCookies();
//            如果没有cookies,则从session中获取sessionid存入cookies中,
//            当我们getSession(),sessionid自动存入cookies中,但是我们要修改它cookies的生命周期这里设置为15秒
        if (cookies == null) {
            session = request.getSession();
//            获取sessionid
            jsessionid = session.getId();
//            Cookie名与路径一致时,可修改Cookie
            cookie = new Cookie("JSESSIONID", jsessionid);
            cookie.setPath("/");
//            生命周期这里设置为15秒
            cookie.setMaxAge(15);
            response.addCookie(cookie);
//            有cookie
        } else {
//            jsessionid=session.getId();需要用到session
            session = request.getSession();
 //        如果有cookie, 遍历cookies 是否有sessionid,有则为之前设置的sessionid的cookie还在生命周期内,无需从session中获取sessionid存入cookies中
  //         在生命周期内关闭打开浏览器,还是一样的sessionid(JSESSIONID)
            for (Cookie cookie1:cookies){
                String name = cookie1.getName();
                if (name.equals("JSESSIONID")){
                    jsessionid=session.getId();
                    break;
                };
            }
//            如果找不到sessionid,则从session中获取sessionid存入cookies中,
            if (jsessionid==null){
                jsessionid = session.getId();
                cookie = new Cookie("JSESSIONID", jsessionid);
                cookie.setPath("/");
//            生命周期这里设置为15秒
                cookie.setMaxAge(15);
                response.addCookie(cookie);
            }
        }
        //        判断自动登录框是否被选择
        boolean check = checkbox1 == null ? false : true;
//       autho用于判断用户是否勾选自动登录,并登录成功的数据,下面设置autho的value为1来表示自动登录。
        response.setContentType("text/html;charset=utf-8");
        Integer autho = (Integer) session.getAttribute("autho");
        if (autho != null && autho == 1) {
            //            在session中查到用户勾选自动登录数据auto,若auto==1,无需输入用户名密码,点击登入直接展示相应页面
        	response.getWriter().write("您已登录,欢迎您! " + "<a href='LogoutServlet'>退出并销毁session</a>");
        } else {
            if (username.equals("zhangsan") && password.equals("111")) {
//                当自动登录被选择时候,在session保存一个key:autho的value为1 用于存储用户已勾选自动登数据
                if (check) {
                    session.setAttribute("autho", 1);
                }
//                没有勾选自动登录,账号密码输入成功,登录成功,点击退出可以回到登录页面
                response.getWriter().write("登录成功! " + "<a href='LogoutServlet'>退出并销毁session</a>");
            } else if (username.equals("") || password.equals("") || username == null || password == null) {
//                账号密码任意框没有输入值的提示,2秒后重定向到登录页面
            	response.getWriter().write("请输入用户名登录! ");
            	response.setHeader("Refresh", "2;url=login.html");
            } else {
//                账号密码输入错误,2秒后重定向到登录页面
            	response.getWriter().write("登录失败! " + "<a href='login.html'>自动返回登录页面</a>");
            	response.setHeader("Refresh", "2;url=login.html");
            }
        }
    }

3、新建LogoutServlet

修改一下doGet方法如下:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.removeAttribute("autho");
            session.invalidate();
        }
        response.sendRedirect("login.html");
        return;
	}

4、测试效果

第一次登录,输入错误的用户名密码,页面自动跳转会登录页面:

点击登录后显示并返回登录页

然后我们输入zhangsan和111并点击记住密码复选框

点击登录跳转

此时,我们直接url返回登录页面

直接点击登录

这次我们点击退出并销毁session,页面会返回登录页面

再次直接点击登录按钮

提示请输入用户名,然后跳转到登录页面

参考资料:

https://baijiahao.baidu.com/s?id=1792235103352395317&wfr=spider&for=pc

https://baijiahao.baidu.com/s?id=1786997538208967885&wfr=spider&for=pc

https://blog.csdn.net/java_faep/article/details/78082802

https://blog.csdn.net/J080624/article/details/78562787

https://blog.csdn.net/afeifu/article/details/137249053

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

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

相关文章

线性表概念及实现1

文章目录 前言一、线性表1.定义2.特点3.一般线性表的抽象数据类型定义 二、线性表的顺序存储&#xff08;顺序表&#xff09;1.基本概念2.数组实现顺序表3.顺序表中基本操作的具体实现 总结 前言 T_T此专栏用于记录数据结构及算法的&#xff08;痛苦&#xff09;学习历程&#…

纯小白蓝桥杯备赛笔记--DAY14(计算几何)

文章目录 计算几何基础平面几何距离圆的周长和面积圆与圆之间的关系&#xff1a;海伦公式计算三角形面积点到直线的距离 点积和叉积例题&#xff1a; 点和线的关系点的表示形式和代码判断点在直线的那边点到线的垂足点到线的距离例题-1242例题-1240升级--点到线段的距离--1285 …

指定世界TOP名校|医学研究学者公派美国麻省理工学院做博士后

W医生公派博士后条件为&#xff1a;世界TOP100的知名高校&#xff0c;研究方向相符且前沿。最终我们用世界顶级高校-美国麻省理工学院&#xff08;MIT&#xff09;的博士后邀请函助其获得单位资助&#xff0c;顺利通过签证并出国。 W医生背景&#xff1a; 申请类型&#xff1a…

LC 501.二叉搜索树中的众数

501.二叉搜索树中的众数 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如果树中有不止一个众数&#xff0c;可以按 任意顺序 返回。 假定 …

全国贫困县DID数据(2008-2022年)

数据来源&#xff1a;国W院扶贫开发领导小组办公室 时间跨度&#xff1a;2008-2022年 数据范围&#xff1a;各县域 数据指标 年份 县域名称 所属地市 所属省份 县域代码 是否贫困县(是为1&#xff0c;否为0) 参考文献&#xff1a; [1]马雯嘉,吴茂祯.从全面脱贫到乡村振兴…

VQ-BeT: Behavior Generation with Latent Actions 代码复现(Mujoco 安装)

代码地址&#xff1a;https://github.com/jayLEE0301/vq_bet_official.git 创建环境 conda create -n vq-bet python3.9 conda activate vq-bet拉取库 git clone https://github.com/jayLEE0301/vq_bet_official.git export PROJ_ROOT$(pwd)安装pytorch conda install pyto…

AI论文速读 | 线性时间序列预测模型分析

论文标题&#xff1a;An Analysis of Linear Time Series Forecasting Models 作者&#xff1a; William Toner&#xff0c; Luke Darlow 机构&#xff1a;爱丁堡大学&#xff08;Edinburgh&#xff09;&#xff0c;华为研究中心&#xff08;爱丁堡&#xff09; 论文链接&am…

开源项目若依放大招了?

前言 鉴于之前写了篇插件式相关的文章&#xff0c;阅读量比起其它文章可不要好太多&#xff0c;所以我决定继续这个主题&#xff01; 以前我们公司用的就是Ruoyi&#xff0c;代码比较简单易懂。但是有些功能确实用不上&#xff0c;比如部门和岗位&#xff0c;每次新项目我拉了…

Docker安装及开启远程访问

这几天有人问我docker是怎么开启远程服务的&#xff1f; 正好之前我做过这件事情&#xff0c;并且写了相关的笔记&#xff0c;现在整理为一篇博客发出来。 安装Docker 首先更新一下自己的yum版本 yum update安装一下所需要的软件包 yum-config-manager --add-repo http://…

Java复习第十七天学习笔记(转发、重定向,GET,POST),附有道云笔记链接

【有道云笔记】十七 4.3 转发、重定向、Get、POST、乱码 https://note.youdao.com/s/GD5TRksQ 一、转发 转发&#xff1a;一般查询了数据之后&#xff0c;转发到一个jsp页面进行展示 req.setAttribute("list", list); req.getRequestDispatcher("student_lis…

套接字通信模型

本文内容主要参考《Android图形显示系统》 套接字也就是socket&#xff0c;一般用于网络中两个主机之间应用进程进行通信&#xff0c;在同一个主机也可以使用套接字完成进程之间的通信。 在图形显示系统中&#xff0c;用到套接字进行通信的地方主要有VSync信号的分发以及输入事…

Linux:动态库加载、编址

目录 一、库的概念 二、动静态库的加载 2.1绝对编址与相对编址 2.1一般程序的加载 三、动态库的加载 一、库的概念 库默认就是一个磁盘级文件&#xff0c;所以在执行代码时&#xff0c;库和可执行程序都会被加载到内存中&#xff0c;从原理上&#xff0c;库函数的调用依旧…

软件测试:遇到bug怎么分析,这篇文章值得一看

为什么定位问题如此重要&#xff1f; 可以明确一个问题是不是真的“bug” 很多时候&#xff0c;我们找到了问题的原因&#xff0c;结果发现这根本不是bug。原因明确&#xff0c;误报就会降低多个系统交互&#xff0c;可以明确指出是哪个系统的缺陷&#xff0c;防止“踢皮球”&…

C--函数指针与回调函数

文章目录 定义函数指针qsort中的回调函数自实现排序的回调函数 定义 回调函数&#xff0c;当一个函数执行时&#xff0c;中途调用其他定义好的函数来帮助实现功能&#xff0c;再继续执行这个函数 函数指针 类型为函数的指针&#xff0c;如下 void func() { } int main() {…

如何让视频流媒体平台免受网络攻击

在各国&#xff0c;流媒体服务已越来越受到大众的欢迎。有统计表明&#xff0c;目前视频流已占网络整体流量的80%以上。不过如您所见&#xff0c;近年来&#xff0c;数字威胁的不断增加&#xff0c;也让网络攻击逐年递增。单个视频用户受到的危险&#xff0c;往往会危及到整个服…

【unity】【C#】游戏音乐播放和发布

今天我们来认识一下有关 unity 音乐的一些知识 我们先创建 AudioClips 文件夹&#xff0c;这个文件夹通常就是 unity 中存放音乐的文件夹&#xff0c;然后拖进音乐文件进去 这里为大家提供了两个音乐&#xff0c;有需要可以自取 百度网盘&#xff1a;https://pan.baidu.com/s…

模型训练----apex库报错IndexError: tuple index out of range

问题描述 在训练模型的过程中遇到了apex库的报错IndexError: tuple index out of range导致无法训练。在github查询后找到了解决方法 问题解决 需要修改/apex-master/apex/amp/utils.py这个文件的代码 从93行开始修改 if x in cache:cached_x cache[x]next_functions_ava…

MySQL学习笔记(三)

1、insert插入多条数据 语法&#xff1a;insert into t_user(字段名1,字段名2...) values(值1,值2...),(值1,值2...),(值1,值2...)...; 2、快速创建表 原理&#xff1a;将一个查询结果当做一张表创建&#xff0c;可以完成表的快速复制。表创建出来&#xff0c;同时表中的数据…

计算机的发展趋势

本文 我们来说计算机的发展趋势 目前来讲 计算机是朝着 巨型化 微型化 网络化 智能化发展 巨型化 指功能巨型化 是指其高速运算、大存储容量和强功能的巨型计算机。其运算能力一般在每秒百亿次以上、内存容量在几百兆字节以上。 主要用于航空航天、军事、气象、人工智能、生…

[Kubernetes[K8S]集群:master主节点初始化]:通过Calico和Coredns网络插件方式安装

文章目录 操作流程&#xff1a;前置&#xff1a;Docker和K8S安装版本匹配查看0.1&#xff1a;安装指定docker版本 **[1 — 7] ** [ 配置K8S主从集群前置准备操作 ]一&#xff1a;主节点操作 查看主机域名->编辑域名->域名配置二&#xff1a;安装自动填充&#xff0c;虚拟…