Tomcat自动生成会话JSESSIONID

一、request.getSession(true)和request.getSession(false)的区别

request.getSession(true):若存在会话则返回该会话,否则新建一个会话,默认为true;

request.getSession(false):若存在会话则返回该会话,否则返回NULL;

当向Session中存放登录信息时,一般建议:HttpSession session =request.getSession();

当从Session中获取登录信息时,一般建议:HttpSession session =request.getSession(false);

最近用到session来存储获取用户登录信息,使用过程中经常会出现获取不到session的情况。

所以对request.getSession()的几种情况查了相关资料,以作知识储备。

在Java Web项目中,用到request.getSession()一般是存储信息到session中或者从session中获取信息。

一般有三种参数设置方式:

  1. request.getSession()
    这是常用的方式,从当前request中获取session,如果获取不到session,则会自动创建一个session,并返回新创建的session;如果获取到,则返回获取到的session;

  2. request.getSession(true)
    这种方法和第一种一样,只是增加了一个true参数,告诉它在获取不到的时候自动创建session;

  3. request.getSession(false)
    这种方法与上两种的区别,就是在获取不到session的时候,不会自动创建session,而是会返回null。

在使用过程中,一般想要存储到session中时,使用request.getSession();想要获取session中的信息时,使用request.getsession(false),并在获取后对session变量进行是否为null的判断,再进行下一步操作。


二、JSESSIONID简介

JSESSIONID就是一个cookie,Servlet容器(tomcat,jetty)用来记录用户session。

2.1、什么时候浏览器自动生成JSESSIONID会话cookie?

  • 创建会话时,即调用request.getSession()的时候;

  • 访问html是不会创建session的,第一次访问JSP页面默认是会创建session的,可以在JSP页面里面关掉自动创建session。我们可以通过添加以下JSP指令:<%@ page session="false" %>就可以禁用JSESSIONID

2.2、览器禁止Cookie时进行URL重写?

服务端在内存里创建session,需要种Cookie,除了在request header里面设置Set-Cookie以外,tomcat等容器有一个URL重写机制。这个机制是浏览器Cookie不可用时的一个兜底策略,通过在URL后面加上;jsessionid=xxx来传递session id,这样即使Cookie不可用时,也可以保证session的可用性。

其中调用Request对象的isRequestedSessionIdFromCookie判断浏览器Cookie是否可用,里面逻辑也很简单,是读取request里面有没有传JSESSIONID这个Cookie。所以网上有些人说第一次访问,其实只要客户端没有传JSESSIONID,tomcat都假定Cookie不可用。

2.3、JSESSIONID什么时候生成并传递到前端的?

如果客户端请求的cookie中不包含JSESSIONID,服务端调用request.getSession()时就会生成并传递给客户端,此次响应头会包含设置cookie的信息

如果客户端请求的cookie中包含JSESSIONID,服务端调用request.getSession()时就会根据JSESSIONID进行查找对象,如果能查到就返回,否则就跟没传递JSESSIONID一样;

2.4、Servlet中调用request.getSession()时底层发生了什么事件?

访问方式:浏览器->服务器

1.如果servlet中没有调用request.getSession()方法,那么服务器永远都不会创建JSESSIONID。

2.如果servlet中调用request.getSession()方法那么情况分为以下两种情况:

 2.1  如果是第一次访问servlet,那么request.getSession()会创建一个JSESSIONID,并且在响应头里面有设置:

 Set-Cookie:JSESSIONID=********************************; Path=/虚拟项目名; HttpOnly

2.2  如果不是第一访问servlet,那么此次浏览器访问该项目的时候,请求头会带有:

Cookie:JSESSIONID=*********************************

request.getSession()会先去获取请求头的JSESSIONID,并且在服务器里面查找该ID,如果该session对象还存活(tomcat默认session的存活时间为30分钟,过了30分钟后,该session对象会被摧毁)则直接获取该session,如果该session已经被摧毁了,则重新又创建一个session对象,重复步骤2.1.

注意:jsp默认调用getSession()方法。


三、如何实现浏览器禁用Cookie后继续使用Session

方法1:

首先要明白:session是在服务器端创建并保存在服务器端,当代码中创建session时会相应地创建sessionID保存在服务器端,同时服务器向浏览器响应信息时会以cookie形式 (其实就是“JSESSION:sessionID”的键值对)返回并保存到浏览器本地中。一旦当前浏览器的进程要取服务器对应的保存在session的信息时候,就会取出刚才保存在cookie中对应的sessionID和服务器端的sessionID进行对比,相同就能取出你想要的信息,不能就不能取出。

好了,明白这一点后,我们就可以即使浏览器禁止了cookie也能用session。因为在一般情况下(即没禁时候),我们不需把sessionID保存到cookie中,因为一般情况下浏览器会自动的;然而当禁止时候,就需要我们主动的把sessionID写入到cookie中。那么问题就解决了。

主动把sessionID写到cookie中:这里其实也可以设置存储JSESSIONID的cookie存活时间

public void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
 
	response.setContentType("text/html;charset=utf-8");
	PrintWriter out = response.getWriter();
	//先用一次Session,就会自动创建Session的id
	HttpSession session=request.getSession();
	session.setAttribute("mess","你关闭了浏览器我还是给你看到session");
	//自己把SessionID保存在cookie中
	Cookie cookie=new Cookie("JSESSIONID", session.getId());
	//设置cookie保存时间
	cookie.setMaxAge(60*20);
	//被创建的cookie返回浏览器
	response.addCookie(cookie);
	out.println("添加Session成功!");
}

直接取就可以了:

String mess=(String)request.getSession().getAttribute("mess");  
out.println(mess);  

方法2:

URL重写

不用保存SessionID到cookie中,而是动态地把当前用户的SessionID添加到程序的各超链接或转发地址中,那么就可以确保用户的唯一。response.encodeRedirectURL(url)是一个进行URL重写的方法, 使用这个方法的作用是为了在原来的url后面追加上Jsessionid 。 目的是保证即使在客户端浏览器禁止了cookie的情况下,服务器端仍然能够对其进行事务跟踪。

//动态改写URL
String url = response.encodeRedirectURL("/UserManager/BuyBookCL");
PrintWriter.println("<a href='"+url+"'>加入购物车</a>");
//在返回时也要加入 URL地址重写
String url = response.encodeRedirectURL("/UserManager/home");
PrintWriter.println("<a href='"+url+"'>返回主页面</a><br/>");

例如这样:

功能:物品加入购物车后,点击返回主页面,主页面显示刚才加入到购物车的物品,当然了,这里是考虑浏览器禁止cookie情况下。


四、JavaWeb设置session失效时间的三种方式

当用户登陆系统后,服务器会设置一个当前session失效的时间,以确保在用户长时间不与服务器交互,自动销毁session,退出登录,释放资源。

4.1、通过web容器配置

在web容器中设置,以Tomcat-9.0.16为例,在安装目录conf\web.xml文件中找到session-config元素,以下是默认配置:

tomcat默认session超时时间为30分钟,可以根据需要修改,负数或0为永不失效。

需要注意这里时间单位为分钟,参数必须为整数。

由于在服务器中设置,则session设置的时间是根据服务器来计算的,而不是客户端。所以如果是在调试程序,应该是修改服务器端时间来测试,而不是客户端。

4.2、通过项目中的web.xml中配置

在项目的web.xml中配置,以Eclipse for JavaEE为例,在WebContent\WEB-INF\lib文件夹下打开web.xml(如没有则手动创建)

同样,时间单位为分钟,这里表示session在创建后10分钟后失效

4.3、通过java代码动态配置

session.setMaxInactiveInterval(10) ; //设置非活跃间隔时间

setMaxInactiveInterval(int second)不同于以上两种方法,并且有几个注意点:

(1)时间单位为秒

(2)此方法表示当前session在指定时间内若没有与服务器发生任何交互后失效

(3)期间用户的任何活动都将刷新session的失效时间,例如在10秒内用户刷新页面将重新计算失效时间

4.4、优先级

如果上述三种方法都设置了,那么优先级按照从高到低:代码设置 > 项目web.xml设置 > 容器web.xml设置(3>2>1)


五、Token和JWT区别

Token都是服务器生成并传递给客户端的,普通token会存在服务端,json web token不用存而已。

JSON Web Token(JWT)是Token的一种实现方案,服务端通过私钥加密用户信息自包含于JWT长字符串的payload载荷中。JWT验证客户端请求发来的token信息,直接在服务端使用私钥解密校验就可以,而不用像普通token在服务端的内存和Redis缓存中保存token信息。

4.1、什么是token?

token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。

当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。

简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。

4.2、token和JWT是什么关系?

为什么实际场景使用的 token 是一个短字符串,如下

25d9048a-dacb-45c3-ac0c-28be4340c8c1

而 JWT 是一个长字符串,如下

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
  • Token是一个很宽泛的概念,翻译为令牌,一般用来表示经过验证之后得到的凭证,长度没有什么限制,多长都可以。JWT是 JSON Web Token,它也自称是一种token,jwt就是一个很具体的标准了,用点号分为三段,分别表示头、信息和签名。Token有很多种,可以是标准的,也可以是你自己定义的,jwt则是其中一种token,而且是标准的token。和我们自己随意定义的token差别大是很自然的,因为我们自己定义的token只需要用来识别用户登录状态,一般很短的唯一uuid都可以实现,通过它可以唯一查询缓存中的用户信息,所以比较短。

  • Token是无状态协议中认证用户的一种形式,相比于传统的cookie,不受域名限制;JWT只是一种实现形式,通过在客户端存储加密后的用户信息payload来降低服务端压力。


参考链接:

JavaWeb设置session失效时间的三种方法以及setMaxInactiveInterval()的注意事项

关于JSESSIONID

java服务器何时创建Session

jsp中session存在问题

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java架构何哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值