JSP、Servlet的Session到底什么时候创建?登录与验证到底和Session有什么关系?

1 测试1[2024-5-23-9:00]

两次获取Session,第一次在查询到用户名密码是否与数据库数据匹配之前,即没有显式地getSession之前;

第二次在查询到用户名密码与数据库数据匹配,显式地getSession之后。

未通过登录验证的Session

在这里插入图片描述
在这里插入图片描述

通过登录验证的Session

在这里插入图片描述
在这里插入图片描述

结论

Session生命周期并不是从第一次执行req.getSession()时创建,这里的第一次指的是程序员第一次显式地在后端程序中写req.getSession()

[2024-5-23-11:02]进一步补充:

流程是服务器启动->自动访问index.jsp->点击登录,访问login.jsp->输入用户名密码->发送servlet请求->后端处理,打印两次session

这个session是由jsp自动创建的,即在自动访问index.jsp时,就已经有了,详见测试2

2 测试2[2024-5-23-10:50]

<%@ page session="ture" %>(默认的,没有显式写出来)

访问index.jsp

在这里插入图片描述
在这里插入图片描述

index.jsp中加一句<%@ page session="false" %>

访问index.jsp

在这里插入图片描述

在这里插入图片描述

再访问login.jsp

login.jsp没加<%@ page session="false" %>,默认会创建session
在这里插入图片描述

在这里插入图片描述

结论

一定程度说明,jsp的本质是servlet

3 GPT-Session的自动创建

是的,自动创建Session以备不时之需确实是一个合理的解释。让我们深入探讨一下这种自动创建Session的行为及其背后的原因。

自动创建Session的原因

  1. 状态管理的需要

    • Web应用需要在多个请求之间保持一些用户的状态信息,如购物车内容、表单数据、用户偏好等。
    • 即使当前请求没有显式使用Session,未来的请求可能会需要Session。因此,提前创建Session可以确保状态管理的准备工作已经完成。
  2. 简化开发

    • 自动创建Session可以简化开发工作,开发人员不必显式地在每个需要状态管理的请求中创建Session。
    • 开发人员可以随时调用request.getSession()而不需要担心Session是否已经创建。
  3. 默认行为

    • 某些容器和框架的设计默认是为了简化开发流程,因此会在合适的时机自动创建Session。
    • 这种行为确保了一致的用户体验和简化的状态管理。

具体示例和行为

JSP页面自动创建Session

在JSP页面中,默认情况下Session是启用的。这是为了确保在页面中使用Session相关功能(如存储用户信息)时,不会因为Session未创建而导致问题。

<%@ page session="true" %>
Servlet自动创建Session

即使在Servlet中没有显式地调用request.getSession(),当某些框架或过滤器需要使用Session时,它们会隐式地调用getSession()方法,这就触发了Session的创建。

实际应用中的影响

用户登录示例

即使在用户未登录的情况下,自动创建Session可以确保未来的请求中,服务器能够方便地存储和访问用户的临时数据。

示例代码

假设你有一个简单的Servlet,它没有显式创建Session:

@WebServlet("/example")
public class ExampleServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 没有显式创建Session
        response.getWriter().println("Hello, World!");
    }
}

尽管在代码中没有调用request.getSession(),但响应中可能仍包含Set-Cookie头,这意味着Session已经被创建。

使用过滤器或框架时的Session创建

一些过滤器或框架可能在处理请求时隐式地调用了getSession(),例如:

  • 安全过滤器:检查用户是否已登录。**【注释】**检查登录肯定要看session里边有没有用户,一旦请求,即使没有也会创建(getSession()默认参数为true)
  • 用户跟踪:记录用户的访问路径和行为。
  • 临时数据存储:如购物车、表单数据等。

这些场景下,即使你在Servlet中没有显式创建Session,框架或过滤器的工作机制也会导致Session的创建。

控制Session的创建

如果你不希望自动创建Session,可以在JSP页面中禁用Session,或者在Servlet中避免调用request.getSession(),并确保框架和过滤器不会隐式创建Session。

禁用JSP页面中的Session
<%@ page session="false" %>
确保Servlet不创建Session

确保在Servlet代码中没有调用request.getSession()

总结

  • 自动创建Session的目的:为了简化开发,确保在未来请求中需要状态管理时Session已经准备好。
  • 常见场景:JSP页面、使用框架和过滤器时会自动创建Session。
  • 控制创建:可以通过配置和代码避免不必要的Session创建。

这种自动创建Session的机制可以确保Web应用在处理状态管理时更加灵活和可靠。**【注释】**可把初学者害惨了

4 登录验证与自动登录

登录验证

单纯的登录验证并不一定需要Session的参与,如果只是简单地控制页面跳转。

功能1 根据登录信息跳转(单纯跳转,并不需要Session)

UserServlet

登录信息匹配------>跳转到相关页面

登录信息不匹配---->跳转到失败页面

功能2 页面右上角展示用户相关信息(需要用到Session)

UserServlet

登录信息匹配------>将登录信息存到session,跳转到相关页面

用户信息展示------>相关页面从session中获取到用户信息并展示

或者不用Session使用转发(重定向不行):

UserServlet

登录信息匹配------>将登录信息存到request,跳转到相关页面

用户信息展示------>相关页面从request中获取到用户信息并展示

本质就是借助域对象存储信息,实现信息的“持久化”

域对象的范围:

  • request的范围只在转发中有效。

  • session的范围是当前这个用户的所有操作都有效。

  • servletContext的范围整个项目都有效。

使用原则:

小的范围能完成功能就放到小的里面。

结合过滤器

LoginFilter

只有少输页面可以不登录访问(过滤器直接放行),对于大多数页面,先要能够通过过滤器才能访问到。

如何通过过滤器?自己写放行条件,一般是是否登录,即从Session中获取登录信息,有就是登录,放行;没有就是未登录,拦截。

过滤器是访问每一个未放行的页面都会存在的,实现一次登录,随意访问的效果,第一次登录将用户名密码存到Session中,

过滤器每次从Session中获取用户名密码并验证,决定是否放行,是一个比较好的做法。

思考:

request是不是也能做?

可以但麻烦且危险,每次请求页面附上用户名密码,然后filter从req里边验证用户名密码

不能一次登录省事

自动登录

即使关闭浏览器,再次访问页面自动完成登录

cookie持久化,定义好路径,发送请求时一起带过去,当请求需要判断是否登录的资源时,根据cookie中的信息,执行登录操作(请求session但是空的,然后执行登录)

还有一个思路(未验证):保存我的sessionid,这样就能直接找到已经存有登录信息的session,不用再去和数据库比对等操作的。(如果密码修改了呢?)

filter只登录没有放行:

需要第二次访问页面才可以出现信息

只从cookie中拿到用户名密码进行了登录,并没继续对这也页面请求的处理,没有放行。

在这里插入图片描述

在这里插入图片描述

5 对于session处理的再思考

modifyPassword修改密码会直接删除SessionManager中所有该用户id关联的记录(键值对),

LoginFilter过滤器会主动查找user对应的session是否可用(是否有键值对),没有则删除该session并重定向至登录;

用户主动注销不会影响session,只是移除其中的user属性;

为了效率->只要user!=null就放行,没有进一步验证->一个账号多处登录,其中一端改密,其他端登录状态不会受到影响->引入会话管理 ->将userid与sessionid绑定->user!=null且会话管理键值对“有效”(存在)才放行->改密时userid所有的键值对标记为“失效”(删掉) ->user!=null且没记录,整个删除session结束会话->重新登录->完成

或者可以在user!=null且没记录时,不删掉整个session,而是移除user属性并重定向,应该也可以实现同样的效果

因为session并不是全局存储结构,一个会话中没法看到其他session,所以没法直接通过遍历所有session并移除user属性的方法, 必须借助一个“全局存储结构”存储每个用户的session,并以此为标记来实现会话同步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值