登录认证(2):会话跟踪技术:Cookie

46 阅读7分钟

为什么需要会话

为了成功完成登录功能,系统需要能够在每次请求时获取用户登录成功的标记。然而,HTTP协议是无状态的协议,每一次HTTP请求都是独立的,服务器不会自动保存任何关于客户端的信息。因此,HTTP请求之间无法直接共享数据。为了解决这个问题并保持用户的状态信息(如是否已登录),我们需要引入会话技术来实现多次请求之间的通信。

会话技术概览

在我们的日常生活中,会话是指谈话、交谈;但是在web开发中,会话是指浏览器和服务器之间的一次连接(第一次连接),当浏览器第一次访问服务器时,会话就建立了。会话的“生命周期”十分长,直到任何一方断开连接,会话才会结束。在一次会话中,一般会包含多次请求和响应

需要特别注意的是:会话是和浏览器关联的,当有多个浏览器和服务器建立连接时,就有多个对话。同一个浏览器在会话结束前,多次对服务器发起请求,多次请求都是属于同一个会话,如图所示,图中有三个浏览器,都和服务器建立了连接,所以说有三个会话,但1、2、3号请求都是属于同一个会话的

image.png

假如关闭了浏览器,则浏览器断开连接,该浏览器对应的对话就结束了,若关闭了web服务器,则web服务器上所有的会话都会立刻结束(这也说明了服务器稳定的重要性)。

会话跟踪

会话跟踪技术是一种维护浏览器状态的技术方法,服务器需要识别多次请求是否来自同一个浏览器,以便在同一次会话的多次请求之间共享数据。(因为HTTP是无状态协议,需要数据共享)

服务器会接收到很多的请求,服务器需要识别到这些请求是否是同一个浏览器发出的。如图所示:

image.png

2、3请求是同一个浏览器发出的,属于同一个会话;而3、5请求不是同一个浏览器(同一种浏览器≠同一个浏览器)发出的,不属于同一个会话,而识别多次请求是否来自同一个浏览器的过程,就是会话跟踪

会话跟踪技术

Cookie

cookie客户端会话跟踪技术,它是存储在客户端浏览器的,使用Cookie进行会话跟踪,需要在浏览器第一次发起请求(建立会话),请求服务器的时候,在服务端设置一个cookie

比如说客户端第一次请求了登录接口,在登录功能执行完毕之后,就可以在服务端设置一个cookie,在cookie中我们可以保存一些用户登录相关的信息,比如用户名用户ID等信息。

在服务端给客户端响应数据时,会自动将设置好、封装了数据的cookie响应给浏览器,浏览器接收到响应的cookie之后,也会自动将其保存在浏览器本地;在后续的每一次请求中,由于请求是来自同一个浏览器,同一个会话,每一次请求都会将浏览器本地存储的cookie自动携带到服务端。

image.png

接下来,服务端就可以获取到请求携带的cookie值,然后判断其值上是否存在。如果存在该cookie的值,那么说明当前用户的登录是成功的;反之,则说明当前用户登录失败。这样我们就可以基于cookie同一次会话的不同请求之间来共享数据。

因为cookieHTTP协议中支持的技术,各大浏览器厂商都支持这一技术;而HTTP协议官方提供了一个和cookie相关的请求头响应头Set-Cookie响应头用于设置Cookie数据 (可以通过HttpServletResponse这个类在服务端中设置cookieCookie请求头用于每一次的请求携带Cookie数据 (同样可以使用HttpServletRequest这个类在服务端获取cookie数据

image.png

操作Cookie

这是一个简单的设置和获取Cookie的后端实例代码:

/**
 * 用于演示Cookie技术的Controller
 */
@Slf4j
@RestController
public class CookieController {

    /**
     * 设置Cookie
     * @param response springboot自动封装的响应对象
     * @return Result<Void>
     */
    @GetMapping("/c1")
    public Result<Void> setCookie(HttpServletResponse response) {
        response.addCookie(new Cookie("login_username", "wzb"));
        return Result.success();
    }

    /**
     * 获取Cookie
     * @param request springboot自动将请求数据封装的请求对象
     * @return Result<Void>
     */
    @GetMapping("/c2")
    public Result<Void> getCookie(HttpServletRequest request) {
        // 请求中可能会有很多Cookie,所以说是得到的Cookie数组
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("login_username")) {
                log.info("login_user: {}", cookie.getValue());
            }
        }
        return Result.success();
    }
}

在服务端代码中,分别操作HttpServletResponse实体对象设置cookie,并给客户端响应;操作HttpServletRequest实体对象获取请求携带的cookie数据。对c1请求路径发起请求:

image.png

我们可以看到在响应头Set-Cookie中,服务端给客户端自动响应了一个login_usercookie,这个cookie正是服务端设置的,并且这个cookie自动存储在浏览器本地的:

image.png

然后再对c2请求路径发起请求,我们可以看到请求头Cookie中请求给服务端自动携带了login_user这个cookie

image.png

服务端也成功获得了这个cookie的值:

image.png

Cookie的优劣

CookieHTTP协议中支持的技术,cookieSet-Cookie响应头中解析、保存到本地浏览器、发起请求自动在Cookie请求头中携带cookie这些操作都是浏览器自动完成的,使用cookie十分方便。

方便的同时,cookie会话技术也有很多缺点,并且有些缺点在当今开发中是致命的! cookie只能在电脑端使用,

移动端(Android&IOS)无法很好的使用cookie

因为cookie存储在本地浏览器,用户可以禁用、删除cookie,不安全, 当用户在本地浏览器禁用cookie或者直接将其删除之后,再次请求服务端就会出现问题:

删除cookie或者禁用cookie

image.png

image.png

再次发起请求,发现报错

image.png

image.png

Cookie不能跨域使用

跨域需要从协议IP地址端口号三个维度看,只要有任何一个维度不同,都属于跨域操作

不支持跨域cookie最大的问题。在我们的学习阶段,虽然是前后端分离开发,但是请求的路径都是localhost(本机),相当于前后端都部署在同一个服务器,所以说cookie是可以使用的。 但是现在的大部分项目,都是前后端分离开发的,在部署的时候,前后端也会部署在不同的服务器中:

image.png

如图所示,我们打开浏览器直接访问前端,访问的urlhttp://192.168.150.200:80/login.html;然后在该页面向服务端发起登录请求,访问的urlhttp://192.168.150.100:8080/login,服务器设置了一个登录使用的cookie响应给浏览器,此时就存在跨域操作了:我们是在http://192.168.150.200:80/login.html这个页面上访问了http://192.168.150.100:8080/login接口,此时服务器设置的cookie是无法使用的。

总结

因为有这些局限,即使cookieHTTP协议官方支持的技术;即使使用十分方便;但在现在的企业开发中,cookie的身影已经减少很多了。还有一种会话技术叫Session,这是底层基于Cookie实现的存储在服务端的技术,且听下回分解。