JavaWeb 之 Cookie 和 Session

由于 Http 是一种无状态的协议,服务器单从网络连接上无从知道客户身份。

会话跟踪是 Web 程序中常用的技术,用来跟踪用户的整个会话。常用会话跟踪技术是 Cookie 与 Session。

Cookie 实际上是存储在客户端上的文本信息,并保留了各种跟踪的信息。

Cookie 工作步骤:

  1. 客户端请求服务器,如果服务器需要记录该用户的状态,就是用 response 向客户端浏览器颁发一个 Cookie。
  2. 客户端浏览器会把 Cookie 保存下来。
  3. 当浏览器再请求该网站时,浏览器把该请求的网址连同 Cookie 一同提交给服务器。服务器检查该 Cookie,以此来辨认用户状态。

注:Cookie 功能需要浏览器的支持,如果浏览器不支持 Cookie 或者 Cookie 禁用了,Cookie 功能就会失效。

Java 中把 Cookie 封装成了javax.servlet.http.Cookie类。

方法 功能
public void setDomain(String pattern) 该方法设置 cookie 适用的域。
public String getDomain() 该方法获取 cookie 适用的域。
public void setMaxAge(int expiry) 该方法设置 cookie 过期的时间(以秒为单位)。如果不这样设置,cookie 只会在当前 session 会话中持续有效。
public int getMaxAge() 该方法返回 cookie 的最大生存周期(以秒为单位),默认情况下,-1 表示 cookie 将持续下去,直到浏览器关闭。
public String getName() 该方法返回 cookie 的名称。名称在创建后不能改变。
public void setValue(String newValue) 该方法设置与 cookie 关联的值。
public String getValue() 该方法获取与 cookie 关联的值。
public void setPath(String uri) 该方法设置 cookie 适用的路径。如果您不指定路径,与当前页面相同目录下的(包括子目录下的)所有 URL 都会返回 cookie。
public String getPath() 该方法获取 cookie 适用的路径。
public void setSecure(boolean flag) 该方法设置布尔值,向浏览器指示,只会在 HTTPS 和 SSL 等安全协议中传输此类 Cookie。
public void setComment(String purpose) 该方法规定了描述 cookie 目的的注释。该注释在浏览器向用户呈现 cookie 时非常有用。
public String getComment() 该方法返回了描述 cookie 目的的注释,如果 cookie 没有注释则返回 null。

CookiemaxAge决定着 Cookie 的有效期,单位为秒。

如果 maxAge 为 0,则表示删除该 Cookie;

如果为负数,表示该 Cookie 仅在本浏览器中以及本窗口打开的子窗口内有效,关闭窗口后该 Cookie 即失效。

Cookie 中提供getMaxAge()setMaxAge(int expiry)方法来读写maxAge属性。

Session

Session 是什么

不同于 Cookie 保存在客户端浏览器中,Session 保存在服务器上。

如果说 Cookie 机制是通过检查客户身上的“通行证”来确定客户身份的话,那么 Session 机制就是通过检查服务器上的“客户明细表”来确认客户身份。

Session 对应的类为 javax.servlet.http.HttpSession 类。Session 对象是在客户第一次请求服务器时创建的。

Session 类中的方法

javax.servlet.http.HttpSession 类中的方法:

方法 功能
public Object getAttribute(String name) 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null。
public Enumeration getAttributeNames() 该方法返回 String 对象的枚举,String 对象包含所有绑定到该 session 会话的对象的名称。
public long getCreationTime() 该方法返回该 session 会话被创建的时间,自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。
public String getId() 该方法返回一个包含分配给该 session 会话的唯一标识符的字符串。
public long getLastAccessedTime() 该方法返回客户端最后一次发送与该 session 会话相关的请求的时间自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。
public int getMaxInactiveInterval() 该方法返回 Servlet 容器在客户端访问时保持 session 会话打开的最大时间间隔,以秒为单位。
public void invalidate() 该方法指示该 session 会话无效,并解除绑定到它上面的任何对象。
public boolean isNew() 如果客户端还不知道该 session 会话,或者如果客户选择不参入该 session 会话,则该方法返回 true。
public void removeAttribute(String name) 该方法将从该 session 会话移除指定名称的对象。
public void setAttribute(String name, Object value) 该方法使用指定的名称绑定一个对象到该 session 会话。
public void setMaxInactiveInterval(int interval) 该方法在 Servlet 容器指示该 session 会话无效之前,指定客户端请求之间的时间,以秒为单位。

Session 的有效期

由于会有越来越多的用户访问服务器,因此 Session 也会越来越多。为防止内存溢出,服务器会把长时间没有活跃的 Session 从内存中删除。

Session 的超时时间为maxInactiveInterval属性,可以通过getMaxInactiveInterval()setMaxInactiveInterval(longinterval)来读写这个属性。

Tomcat 中 Session 的默认超时时间为 20 分钟。可以修改 web.xml 改变 Session 的默认超时时间。

例:

1
2
3
<session-config>
<session-timeout>60</session-timeout>
</session-config>

存取方式

Cookie 只能保存ASCII字符串,如果需要存取 Unicode 字符或二进制数据,需要进行UTF-8GBKBASE64等方式的编码。

Session 可以存取任何类型的数据,甚至是任何 Java 类。可以将 Session 看成是一个 Java 容器类。

隐私安全

Cookie 存于客户端浏览器,一些客户端的程序可能会窥探、复制或修改 Cookie 内容。

Session 存于服务器,对客户端是透明的,不存在敏感信息泄露的危险。

有效期

使用 Cookie 可以保证长时间登录有效,只要设置 Cookie 的maxAge属性为一个很大的数字。

而 Session 虽然理论上也可以通过设置很大的数值来保持长时间登录有效,但是,由于 Session 依赖于名为JESSIONID的 Cookie,而 Cookie JESSIONIDmaxAge默认为-1,只要关闭了浏览器该 Session 就会失效,因此,Session 不能实现信息永久有效的效果。使用 URL 地址重写也不能实现。

服务器的开销

由于 Session 是保存在服务器的,每个用户都会产生一个 Session,如果并发访问的用户非常多,会产生很多的 Session,消耗大量的内存。

而 Cookie 由于保存在客户端浏览器上,所以不占用服务器资源。

浏览器的支持

Cookie 需要浏览器支持才能使用。

如果浏览器不支持 Cookie,需要使用 Session 以及 URL 地址重写。

需要注意的事所有的用到 Session 程序的 URL 都要使用response.encodeURL(StringURL)response.encodeRediretURL(String URL)进行 URL 地址重写,否则导致 Session 会话跟踪失效。

跨域名

  • Cookie 支持跨域名。
  • Session 不支持跨域名。

参考资料