Java-030-cookie和session

Session和Cookie

HTTP是无状态协议

之前我们学习HTTP协议的时候, 我们提到过, HTTP协议是无状态的!, 这个无状态是什么意思呢? 那首先我们来看一下有状态是什么样的.

有状态连接

  • 客户端第一次给服务端发送请求1, 然后连接建立起来了
  • 客户端第二次给服务端发送请求2, 这时候, 服务端自然知道这个请求是来自客户端的
    这个状态就是说, 客户端和服务端是可继续延续之前的请求, 然后继续.

无状态

就是说, 默认情况下, 每个HTTP请求都是独立的, 和之前的请求和之后的请求都没有关系.

那问题来了, 如何基于无状态的HTTP协议, 实现有状态的Web应用功能呢? 例如:

  • 登录状态
  • 浏览记录

Session (会话)

我们引入一个抽象概念, Session. 首先, 清空自己对这个概念的主观认识. Session不是Web开发的概念, 和Cookie也没有必然关系. 这是一个独立的概念!

Session — 指的就是一种状态, 客户端和服务端连接中的会话状态! 以便让每次请求能够延续之前请求.

回到Web开发, 我们需要基于无状态的HTTP协议, 实现有状态的Web应用功能, 本质上就是要实现一个Session的机制, 维护上一次请求的状态 (已完成或未完成). 为了维护这个状态, 则需要存储:

客户端

第一种选择是在客户端存储和维护Session, 每次给服务端发送请求的时候, 在请求中夹带Session信息.

服务端

第二种选择是在服务端存储和维护Session, 然后每次处理客户端的请求时候, 从存储中找出与与这个客户端对应的Session信息.

但是这里有个问题, 服务端需要把客户端发来的请求和服务端存储的Session信息对应上, 则客户端发来的请求还是需要夹带一个状态, 让服务端能够把这个请求和对应的客户端对应上.

比如:

  • 客户端可以在请求中的authentication字段夹带一个SessionId或Session密钥.
  • 客户端可以在请求中的cookie字段夹带一个SessionId或Session密钥.
  • 客户端可以在请求中的RequestBody夹带一个SessionId或Session密钥.
  • 等等

当服务端接收到请求,, 然后解析出请求中的这个Session密钥, 则可以把这个请求和对应的Session信息对应起来, 恢复出上一个请求的状态信息.

Cookie就是HTTP协议提供的一个机制, 能够在请求中夹带信息, 用于记录状态. 基本的操作流程是:

  1. 客户端给服务端发送请求.
  2. 服务端在HTTP响应中, 添加Cookie信息, 一起返回给客户端.
  3. 客户端接收到请求的响应. 把Cookie信息存储在本地, 之后发送给服务端的请求中, 都会夹带这个Cookie信息(浏览器默认功能).
  4. 服务端接收到这个Cookie信息, 就能够恢复出之前状态信息.

比如我们使用Cookie实现Session:

  1. 客户端给服务端发送请求.
  2. 服务端接收到请求之后, 在存储中创建这个这个客户端的Session信息, 并且把这个Session的Id添加到Cookie中, 返回给客户端.
  3. 客户端接受到请求响应之后, 把Cookie信息存储在本地, 之后发送给服务端的请求中, 都会夹带这个Cookie信息(浏览器默认功能).
  4. 服务端再接收到这个客户端的请求, 解析出其中的Cookie信息 (包含SessionId), 通过这个SessionId提取出响应的Session信息, 恢复出之前和这个客户端之前请求的状态.

安全性

Cookie盗用

我们很容易感觉到, Cookie里存储的SessionId是用来和服务端存储的Session有一一对应关系. 如果存储在客户端的Cookie信息被盗之后, 黑客可以使用这个SessionId, 伪造请求发送给服务端, 从而可以恢复出在服务端的Session信息, 从而可以利用.

威胁

本地存储

  • 本地加密
  • 防止跨站攻击

传输

加密存储HTTPS (HTTP + SSL), 也就是使用可以加密的请求.

服务端存储

有效期, Session有有效期, 需要重新提供认证信息.

代码链接

相关链接