用户状态保持机制-Session

news2024/11/29 12:41:17

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1572. 【基础赛】涂色(paint)

1572. 【基础赛】涂色&#xff08;paint&#xff09; (Input: paint.in, Output: paint.out) 时间限制: 2 s 空间限制: 256 MB 具体限制 题目描述 Introl获得了一个N行的杨辉三角&#xff0c;他将每行中值为奇数的位置涂为了黑色。 Chihiro将提出M次询问&#xff0c;在第L…

51单片机上面的IIC协议

1、什么是IIC协议 2、模拟IIC协议 51单片机上面是没有与IIC协议相关的寄存器的&#xff08;没有相关的硬件&#xff09;&#xff0c;不像串口可以配置对应的寄存器达到目的&#xff08;比如修改波特率9600 or 115200&#xff09;&#xff0c;要配置IIC只能够根据用户手册里面的…

【LeetCode】单调栈类题目详解

所有题目均来自于LeetCode&#xff0c;刷题代码使用的Python3版本 单调栈 通常针对一维数组的问题&#xff0c;如果需要寻找一个元素右边或者左边第一个比自己大或者小的元素的位置&#xff0c;就可以使用单调栈&#xff0c;时间复杂度为O(n) 单调栈的本质是空间换时间&#…

[AIGC] Spring中的SPI机制详解

文章目录 1. 什么是SPI2. Spring中的SPI机制3. Spring SPI的工作流程4. Spring SPI的应用 1. 什么是SPI SPI &#xff08;Service Provider Interface&#xff09;是Java中服务提供者接口的缩写&#xff0c;它是Java提供的一种用于被第三方实现或扩展的接口&#xff0c;SPI的作…

2024 年最新前端工程师使用 Webpack 模块打包工具详细教程(更新中)

概述 Webpack 模块打包工具 Webpack 是一个现代的静态模块打包工具&#xff0c;用于将前端应用程序的各种资源&#xff08;例如如&#xff1a;JavaScript、CSS、图片等&#xff09;视为模块&#xff0c;并将它们打包成可以在浏览器中运行的静态文件。它的主要功能包括模块打包…

对 FileReader 的理解

1、文档 FileReader - Web API 接口参考 | MDN 2、概念 FileReader 对象是一个内置的 JavaScript 对象&#xff0c;用于在客户端&#xff08;浏览器&#xff09;中异步读取文件内容。 它提供了一种在 Web 应用程序中读取文件数据的方式&#xff0c;可以读取文件内容并将其转…

跟TED演讲学英文:The next grand challenge for AI by Jim Fan

The next grand challenge for AI Link: https://www.ted.com/talks/jim_fan_the_next_grand_challenge_for_ai? Speaker: Jim Fan Date: October 2023 文章目录 The next grand challenge for AIIntroductionVocabularyTranscriptSummary后记 Introduction Researcher Jim…

MySQL事务、主从、分库分表常见面试题

文章目录 1.事务的特性2.并发事务问题&#xff0c;如何解决&#xff0c;默认隔离级别3.undo log和redo log的区别4.事务中的隔离性是如何保证的&#xff08;解释一下MVCC&#xff09;5.主从同步原理6.分库分表 1.事务的特性 2.并发事务问题&#xff0c;如何解决&#xff0c;默认…

2022年蓝桥杯省赛软件类C/C++B组----积木画

想借着这一个题回顾一下动态规划问题的基本解法&#xff0c;让解题方法清晰有条理&#xff0c;希望更多的人可以更轻松的理解动态规划&#xff01; 目录 【题目】 【本题解题思路】 【DP模版】 总体方针&#xff1a; 具体解题时的套路&#xff1a; 【题目】 【本题解题思…

压缩列表ziplist

目录 1压缩列表的结构 2.压缩列表节点的构成 previous_entry_length encodeing conent 3.压缩列表API 1.创建列表 ziplistNew 2.正向遍历 ziplistNext 3.反向遍历 ziplistPrev 4.插入元素 ziplistInsert 5.级联更新 __ziplistCascadeUpdate 6.删除节点 7.查找entr…

L2-2 巴音布鲁克永远的土(二分+并查集)

思路&#xff1a;我们可以二分答案&#xff0c;然后判断当前答案合不合理。 对于判断答案合理&#xff0c;可以用并查集&#xff0c;看mid能否把所有检查点连进一个集合中&#xff0c;枚举每个结点&#xff0c;如何当前结点周围的四个方向可以连的话&#xff0c;就加进同一个集…

host文件nginx代理 综合理解

之前一直理解得很糙 导致遇到问题很迷糊 今天经过大佬两句话讲明白了 特此记录 host文件 首先host做了代理 也就是对浏览器的DNS寻址做了拦截 具体原理可以参照当我们在地址栏输入URL的时候浏览器发生了什么 例如127.0.0.1 www.baidu.com 将 127.0.0.1 www.baidu.com 链接自…

DHCP抓包分析

DHCP动态路由配置协议&#xff0c;是C/S架构&#xff0c;由DHCP服务器为客户端动态分配IP信息。 DHCP客户端首次接入网络数据交互过程&#xff1a; 如何解决IP地址的冲突&#xff1a; ▫ DHCP服务器端&#xff1a;收到DHCP DISCOVER报文时&#xff0c;给客户端分配IP地址前会发…

有关NVIDIA 4090的pytorch版本安装心得

目录 1.查看版本2.安装对应版本的pytorch3.检测是否安装成功4.问题 1.查看版本 输入 nvidia-smi 查看GPU支持的cuda最高版本 如上图所示&#xff0c;你的GPU支持的最高CUDA版本便为12.2&#xff0c;所以你要安装CUDA版本不能高于该版本。安装版本不能太低&#xff0c;建议就小…

高阶流程图(SIPOC)

SIPOC高阶流程图是一种流程映射和改进方法&#xff0c;它使用可视化的方式描述一个或多个流程的输入和输出。SIPOC是五个单词的首字母缩写&#xff0c;分别代表供应商&#xff08;Suppliers&#xff09;、输入&#xff08;Inputs&#xff09;、过程&#xff08;Processes&#…

python使用概率算法模拟寻找伴侣

对于模拟寻找伴侣的问题,人在特定时期内能够遇见的异性是有限的,假设在某段时期内能够遇见的异性人数是n,那么问题在于在不能全面对n位候选人进行评估的情况下,以最大概率选中最好的那位。 假设n位候选人的水平用n个不同的数值表示,数值越大表示其水平则越高,问题在于,…

深入剖析Tomcat(一) 实现一个简单的Web容器

前言 在Java生态中&#xff0c;Tomcat的应用可谓经久不衰&#xff0c;众多Java Web应用都依赖它来进行部署。 虽然我们经常使用它&#xff0c;但是如果不深入了解的话&#xff0c;它对我们来说就一直是一个黑盒。就单纯的作为一个使用者来说&#xff0c;肯定也知道它内部应用…

Win10下安装Anaconda

Anaconda是可以便捷获取包且对包能够进行管理&#xff0c;同时对环境可以统一管理的发行版本&#xff0c;它包含了conda、Python在内的超过180个科学包及其依赖项。 安装Anaconda Anaconda官方下载网址&#xff1a;https://www.anaconda.com/download 官网页面中&#xff0c…

探究 ChatGPT 的心脏--Transformer(基础知识第一篇)

Transformer 是 ChatGPT 的核心部分&#xff0c;如果将 AI 看做一辆高速运转的汽车&#xff0c;那么 Transformer 就是最重要的引擎。它是谷歌于 2017 年发表的《Attention is All You Need》中提出的 Sequence-to-sequence 的模型&#xff0c;诞生之后便一统江湖&#xff0c;在…