1. Cookie && Session
1.1 Cookie && Session
- Cookie是什么? Cookie是浏览器提供的持久化存储数据的机制.
- Cookie从哪里来?
Cookie从服务器返回给浏览器.
服务器代码中由程序员决定要把什么信息保存到客户端.通过HTTP响应的
Set-Cookie
字段,把键值对写回去. - Cookie到哪里去?
Cookie会在后续浏览器访问服务器的时候带到请求的
headler
中发给服务器. 注意的是,服务器不是只给一个客户端提供服务,是同一时间要处理多个客户端.此时服务器就可以通过cookie中的值,来识别当前客户端是谁.当前客户端的服务提供到哪个环节. - Cookie存储在哪里? 存储在浏览器(客户端)所在主机的硬盘中,浏览器会根据 域名 来分别存储.
Cookie有一个最为典型的应用:标识用户的身份信息.
在网站中有个登录功能:比如淘宝, 我们登录一次网站后, 后续再使用访问淘宝的其他页面, 是不需要再次登录的, 还有自动登录功能, 隔了一段时间再次访问淘宝网站, 我们会发现此时并不需要再次输入账号密码登录, 网站就会自动地帮我们登录.
针对登录操作,淘宝会查询数据库,验证用户的用户名和密码是否正确.如果正确,登录成功. 淘宝就会把当前用户的身份信息在内存中也保存一份. 同时给这个用户分配一个表示身份的序号.(可能是个整数/字符串,唯一性).我们把这个生成的唯一身份序号称为sessionId. 服务器使用像hash表这样的结构把序号作为key,身份信息作为value存储起来.服务器把生成的这些键值对称为Session(会话).
服务器给客户端返回的 Cookie 里面就包含 SessionId, 浏览器就会在本地将这个 Cookie 储存起来, 后续浏览器发送请求的时候就会带上这个 Cookie, 服务器收到 Cookie 中的身份序号后, 就会查询 Session 会话表, 如果存在就会可以正常访问, 不用重复的输入账号与密码, 否则就需要用户重新输入账号密码进行登录.
有时候我们会发现登录网站后隔一段时间再次登录, 会出现让我们再次输入账号密码的情况, 此时就是登录状态失效过期了, 这种情况可能是可能是客户端把 Cookie 删了, 也可能是服务器这把对应的身份信息删了.
注意理解 Cookie 和 Session 之间的区别和关联. 关联: 在网站登录功能中可以搭配使用. 区别:
- Cookie 是客户端的存储机制, Session 是服务器的存储机制.
- Cookie 里面可以存各种键值对 (还可以存除 SessionId 以外的), Session 则专门用来保存用户信息.
- Cookie 完全可以单独使用, 不搭配 Session (实现非登录的场景), Session 也可以不搭配 Cookie (手机 App 登录服务器, 此时也需要 Session, 但这里没有 Cookie 的概念, Cookie 和浏览器强相关的).
- Cookie 是 HTTP 协议中的一个部分, Session 则可以和 HTTP 无关 (TCP, WebSocket …也可以用 Session).
1.2 Servlet会话管理操作
在 HttpServletRequest
类中, 可以使用 getSession
来获取或者创建会话, getCookies
可以获取请求中的 Cookie 列表.
方法 | 描述 |
---|---|
HttpSession getSession() | 在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null |
Cookie[] getCookies() | 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对. |
调用 getSession
方法所做的事情:
getSession
有一个 boolean
类型的参数, 如果参数是 true
, 它有如下行为:
- 读取
cookie
里的sessionId
字段. - 根据
sessionld
来查询对应的HttpSession
对象在服务器上是否存在. - 如果不存在, 就创建一个新的会话, 即创建一个新的
HttpSession
对象, 并生成一个唯一的sessionId
, 会以新生成的sessionId
作为Key
, 生成的HttpSession
对象作为Value
, 以键值对形式储存到类似于Hash
的结构中, 然后将sessionId
设置到响应报文中的set-Cookie
字段返回给浏览器. - 如果存在就直接返回查询到的
HttpSession
对象.
如果参数是 false
, 行为如下:
- 读取
cookie
里的sessionId
字段. - 根据
sessionld
来查询对应的HttpSession
对象在服务器上是否存在. - 如果不存在, 直接返回
null
. - 如果存在就直接返回查询到的
HttpSession
对象.
总之, getSession
的参数为true
时允许创建 Session 会话, 为false
时不允许创建 Session 会话.
关于HttpSession:
这个对象也可以看作是一个哈希表, 是以键值对的形式存储数据的, 并且允许程序员在对象中储存任意的键值对数据, 但是 Key
必须是 String
类型,Value
的类型是 Object
, 设置就比较随意了.
方法 | 描述 |
---|---|
Object getAttribute(String name) | 查询 session 会话中指定键的键值, 查不到则返回 null. |
void setAttribute(String name, Object value) | 绑定一个键和值到该 session 会话中 |
boolean isNew() | 判定当前是否是新创建出的会话 |