状态跟踪

99 阅读5分钟

状态跟踪

http 协议是一种无状态的协议,当请求/响应完成后,连接会断开。服务器会认为每次请求的用户都是新用户,从而无法跟踪用户的状态。但是,在开发中,很多时候服务器需要跟踪用户的状态,从而进行一系列的商务活动。如何让服务器知道,这一系列的请求都是同一个用户的行为呢?

WEB 服务器跟踪状态的方式有五种:

1、隐藏表单

2、cookie

3、session

4、URL 重写

5、JWT


隐藏表单

利用 隐藏表单向服务器发送请求。在隐藏表单中存放该用户的唯一标识。服务器在接收到隐藏表单后,发现两个请求的表单数据一致,就认为是同一个用户。

缺点:

1、每个页面的的每个请求,都得加上用户唯一标识的隐藏表单,很是繁琐。

2、用户唯一标识,必须由开发者自己书写算法。


Cookie

cookie 是服务器端发送给客户端的一段文本。

工作流程:

客户端访问服务器。服务器利用 resp.addCookie(Cookie 对象),向客户端发送 Cookie 信息。产生响应时,会产生 Set-Cookie 响应头,并附加 Cookie 信息。当客户端再次请求服务器,会将之前服务器发送给客户端的 Cookie 信息,再以 Cookie 请求头的方式发送给服务器。服务器发现发送和接收的 Cookie 信息一致就认为是同一个用户。

Cookie 的分类

cookie 在客户端存放的方式有两种:

1、存放在客户端浏览器的缓存中,当浏览器不关闭时,可以一直将缓存中 coookie 信息发送给服务器。当浏览器关闭,缓存消失,cookie 信息随之消失。

2、如果在 cookie 中设置了过期时间,那么 cookie 信息在发送客户端以后,会以文件方式存放在客户端,在过期时间内,可以一直将 cookie 信息发送给服务器。

向客户端发送 cookie 信息:

//创建 cookie 对象
Cookie c1 = new Cookie("name","tom");
Cookie c2 = new Cookie("userId","2");
//设置过期时间:1分钟以后过期
c2.setMaxAge(60);
​
//向客户端发送 cookie 信息
response.addCookie(c1);
response.addCookie(c2);

服务器得到 Cookie 信息:

//得到客户端提交的 Cookie 信息
Cookie[] cookieArray = request.getCookies();
String str = "";
for (Cookie c : cookieArray){
    str += "键:"+c.getName()+" 值:"+c.getValue();
}

Cookie 的缺陷:

1、Cookie 信息以文本方式存放在客户端,容易引起安全隐患。

2、用户的唯一标识,同样需要开放者自行编写。


Session

Session 是服务器端用于跟踪客户端信息的对象。

工作流程:

客户端第一次访问服务器,服务器调用 req.getSession() 为该用户创建跟踪状态的 Session 对象。同时给该对象分配一个唯一标识 sessionId。为了管理不同用户的 seesion 对象,服务器会以 sessionId 为键,session 对象为值的方式,存放于服务器管理 session 的 Map 集合。产生响应时,服务器会将 sessionId 以 Set-Cookie 响应头的方式发送给客户端。

客户端再次请求服务器,会将 sessionId 再以 Cookie 请求头的方式发送给服务器。服务器得到 sessionId 后,从 Map 集合中,得到对应的 session 对象,从而跟踪用户状态。


创建/获得 session:

//如果有存放该用户信息的 session对象,则直接取出,否则,为该用户创建 session对象
HttpSession session = request.getSession();

在 session中绑定/获取共享数据:

//如果有存放该用户信息的 session对象,则直接取出,否则,为该用户创建 session对象
HttpSession session = request.getSession();
//在 session中绑定共享对象,在一个会话范围内共享
session.setAttribute("userName","tom");

从 session中取出共享对象:

HttpSession session = request.getSession();
//从 session中取出共享对象
Object obj = session.getAttribute("userName");

session 的销毁:

http 协议是无状态的协议,当用户关闭浏览器下线时,服务器并不清楚。因而还会保留分配给该用户的 session 对象。所以,关闭浏览器,并不意味着 session 对象的销毁。

如果不及时清理这种过期的 session 对象,服务器的内存会持续的占用,持续的消耗,最终导致服务器的崩溃。

销毁 session 的方式:

1、设置过期时间

session.setMaxInactiveInterval(1800);//单位为秒

从用户最后一次访问服务器的时间开始,到当前时间为止。如果超过过期时间,服务器就会认为客户端已经下线,从而销毁为该用户分配的 session对象。

spring Boot中设置过期时间:

时间描述:默认为正,负以-开头,紧接着P,(字母不区分大小写)
D :天
T:天和小时之间的分隔符
H :小时
M:分钟
S:秒
每个单位都必须是数字,且时分秒顺序不能乱。
server:
  servlet:
    session:
      timeout: PT10M

2、调用 invalidate() 强行销毁 session

session.invalidate();

3、应用程序结束或服务器崩溃


session 和 cookie的区别

1、session 是服务器端的对象,cookie 是服务器发送给客户端一段文本。

2、在 session 中可以绑定共享对象,而 cookie 信息只能传输文本。

3、cookie 在客户端和服务器之间传输的是具体的数据,容易引起安全隐患。而 session 在客户端和服务器之间只传输 sessionId,数据较安全。


URL 重写

由于使用 cookie 会存在一些安全隐患,有些用户会在客户端浏览器对cookie 进行禁用。这样,当使用 session 进行会话跟踪时,由于不能使用 cookie,那么也就无法通过 cookie 方式向服务器发送 sessionId。

服务器得不到 sessionId,就认为这是新用户,从而会重新分配新的 session 对象。导致无法进行状态跟踪。

解决方案是 URL 重写。在访问浏览器时,在 URL 路径中,附加 sessionId。这样,即使客户端禁用了 cookie,服务器同样可以得到 sessionId,从而跟踪状态。

<a href="/lovobook;jsessionid=
CC6733BEF4ADB9FAEB52B1CA1AF81CF6">Click</a>

在服务器端,可以调用 response 的 恩从的RedirectURL() 方法,对请求的 URL 重新进行编写,从而附加 sessionId 信息。

response.encodeRedirectURL("/lovobook/sucess.html")

\