Session & Cookie 详解及应用

Session

Session 对应的类为 javax.servlet.http.HttpSession 类。每个来访者对应一个 Session 对象,所有该客户的状态信息都保存在这个 Session 对象里。Session 对象是在客户端第一次请求服务器的时候创建的。Session 也是一种 key-value 的属性对,通过 getAttribute(String key)setAttribute(String key,Object value) 方法读写客户状态信息。Servlet 里通过 request.getSession() 方法获取该客户的 Session。

Session 的使用比 Cookie 方便(例如直接保存某个对象,而 Cookie 则是基于字符串来操作),但是过多的Session 存储在服务内存中,会对服务器造成压力。

Session 与 Cookie 的联系:HTTP 协议是无状态的,Session 不能依据 HTTP 连接来判断是否为同一客户。在一般情况下,服务器对用户的判断是依赖于 Cookie 中被存入的值 SESSIONID (服务端在创建Session的时候产生)的。有时候为了安全性,我们会不使用预存 SESSIONID 的方法,转而使用URL重写技术

Session攻击(会话劫持+固定)与防御

Session 超时时间

随着越来越多的用户访问服务器,Session 也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的 Session 从内存删除,这个时间就是 Session 的超时时间。也就是说, Session 超时的概念是客户端两次请求的最大间隔时长。在 Tomcat 中的默认超时时间是 30 min。

超时时间属性为 maxInactiveInterval,可以通过对应的 getMaxInactiveInterval() 获取,通过 setMaxInactiveInterval(long interval) 修改。也可以在 web.xml (application.properties) 中修改。

另外,通过调用 Session 的 invalidate() 方法可以使 Session 失效。


Cookie

Cookie 是一段不超过 4KB 的小型文本数据,由一个 Name、一个 Value 和其它几个用于控制 Cookie 有效期、安全性、使用范围的可选属性组成。

Cookie 由服务器端生成,通过响应报文 (Set-Cookie) 发送给客户端。浏览器会将 Cookie 的 key/value 保存到某个目录下的文本文件内,下次请求同一网站时就发送该 Cookie 给服务器,以供其判断 web 状态信息。

Cookie 组成

  1. Name/Value:设置 Cookie 的名称(通常来讲 name 是不区分大小写的)及相对应的值。对于“认证Cookie”,Value 值包括 Web 服务器所提供的访问令牌 。
  2. Expires 属性:设置 Cookie 的生存期,这个值是 GMT 时间格式的。如果设置了 Cookie 将会被存储于磁盘中,如果没有则会被存储于浏览器内存中。
  3. Path 属性:定义了Web站点上可以访问该Cookie的目录。例如:
cookie.setPath(req.getContextPath + "/eg");  // => /工程路径/eg
  1. Domain 属性:指定了可以访问该 Cookie 的 Web 站点或域。Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。当需要实现单点(Single Sign On)登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie 受攻击的危险,比如攻击者可以借此发动会话定置(Session Fixation)攻击。
  2. Secure 属性:设置了 Secure 属性的 cookie,只能通过 https 的方式来发送 cookies。使用 HTTPS 安全协议,可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改。
  3. HTTPOnly 属性 :设置了 HTTPOnly 属性,javascript 代码将不能操作 cookie。用于防止客户端脚本通过 document.cookie 属性访问 Cookie,有助于保护 Cookie 不被跨站脚本攻击窃取或篡改。

Cookie 过期属性

Max-age

document.cookie = 'foo=bar;path=/;max-age='+5*60+';';

Expires(需要指定具体日期繁琐)

var d = new Date();
d.setTime(d.getTime() + 5*60*1000); // in milliseconds
document.cookie = 'foo=bar;path=/;expires='+d.toGMTString()+';';

只需要设置一个,如果同时设置,Max-age 优先级更高,如果两个都不进行设置,该 cookie 将会是一个"session cookie",即 cookie 的有效时间为该会话,当浏览器关闭后 cookie 失效

设置 cookie 失效

当服务端想让客户端删除一个 cocokie 时,会利用 Max-age 设置其过期 setMaxAge(int expiry),给客户端颁发一个同名 cookie(此时一般会将 value 设置成空白字符串)。注意!当 expiry 值为负数时(默认为 -1),cookie 会在浏览器关闭后删除;而当 expiry 值为 0 时, cookie 会被立刻删除。

Cookie 中存取中文

使用 URLEncoder 类里的 encode(String s, String enc) 方法进行中文转码

Cookie cookie = new Cookie("userName", URLEncoder.encode("孤傲苍狼", "UTF-8"));

在获取 cookie 中的中文数据时,再使用 decode(String s, String enc) 进行解码

URLDecoder.decode(cookies[i].getValue(), "UTF-8")

Cookie 应用实例

免登录

将账号、密码等登录信息保存在 cookie 中,并控制 cookie 的有效期,下次访问时再验证 cookie 中的信息即可。

  • 方案一:把登录的时间戳保存到 cookie 与数据库中,再次访问时到数据库中验证用户名与登录时间戳即可。

  • 方案二:把账号按照一定的规则加密后,连同账号一块保存到Cookie中。下次访问时只需要判断账号的加密规则是否正确即可。例如把账号保存到名为account的Cookie中,把账号用MD1算法加密后保存到名为ssid的Cookie中。验证时验证Cookie中的账号加密后是否与Cookie中的ssid相等。该方案只在登录时查询一次数据库,以后访问验证登录信息时不再查询数据库。

关于 Cookie & Session 失效的细节

  1. 如果客户的两次请求时间间隔长于了超时时间,那么 Session 失效。
  2. 如果 Cookie 没有设置过期时间,那么默认是关闭浏览器再删除。如此,在浏览器没有关闭之前, Session 可能已经失效,此时 name 为 "SessionID" 的 Cookie 虽然没被删除,但因为在后台找不到相应的对象,所有也不起作用了。如果再次访问服务端会重新颁发一个 SessionID 给 Cookie。(恰恰是由于关闭浏览器不会导致 Session 被删除,服务器才需要为 Session 设置了一个失效时间)
  3. 如果在 Session 超时时间内,关闭了浏览器,默认时效的 Cookie 会被删除。再次打开网页,即便是原 Session 还未被清除,但因为客户端丢失了 ID,只能在让服务端另外创建一个 Session 并发送其 ID 过来。


参考

https://mrcoles.com/blog/cookies-max-age-vs-expires/

https://baike.baidu.com/item/cookie/1119

https://www.cnblogs.com/l199616j/p/11195667.html

https://www.bilibili.com/video/BV1Y7411K7zz?p=269

https://www.cnblogs.com/l199616j/p/11195667.html

你可能感兴趣的:(Session & Cookie 详解及应用)