`

【Web开发】说说Session和Cookie

阅读更多

 Session 与 Cookie 的作用都是为了保持访问用户与后端服务器的交互状态。它们有各自的优点,也有各自的缺陷,使用 Cookie 来传递信息时,随着 Cookie 个数的增多和访问量的增加,它占用的网络带宽也很大,试想假如 Cookie 占用 200 个字节,如果一天的 PV 有几亿,它要占用多少带宽?所以有大访问量的时候希望用 Session,但是 Session 的致命弱点是不容易在多台服务器之间共享,所以这也限制了 Session 的使用。

 

Cookie

 

Cookie 的作用我想大家都知道,通俗地说就是当一个用户通过 HTTP 协议访问一个服务器的时候,这个服务器会将一些 Key/Value 键值对返回给客户端浏览器,并给这些数据加上一些限制条件,在条件符合时这个用户下次访问这个服务器的时候,数据又被完整地带回给服务器。

 

这个作用就像您去超市购物时,第一次给您办张购物卡,这个购物卡里存放了一些您的个人信息,下次您再来这个连锁超市时,超市会识别您的购物卡,下次直接购物就好了。

当初 W3C 在设计 Cookie 时实际上考虑的是为了记录用户在一段时间内访问 Web 应用的行为路径。由于 HTTP 协议是一种无状态协议,当用户的一次访问请求结束后,后端服务器就无法知道下一次来访问的还是不是上次访问的用户,在设计应用程序时,我们很容易想到两次访问是同一人访问与不同的两个人访问对程序设计和性能来说有很大的不同。例如,在一个很短的时间内,如果与用户相关的数据被频繁访问,可以针对这个数据做缓存,这样可以大大提高数据的访问性能。Cookie 的作用正是在此,由于是同一个客户端发出的请求,每次发出的请求都会带有第一次访问时服务端设置的信息,这样服务端就可以根据 Cookie 值来划分访问的用户了。

 

当前 Cookie 有两个版本:Version 0 和 Version 1。通过它们有两种设置响应头的标识,分别是 “Set-Cookie”和“Set-Cookie2”。这两个版本的属性项有些不同。

 

Set-Cookie

属性项 属性项介绍
NAME=VALUE 键值对,可以设置要保存的 Key/Value,注意这里的 NAME 不能和其他属性项的名字一样
Expires 过期时间,在设置的某个时间点后该 Cookie 就会失效,如 expires=Wednesday, 09-Nov-99 23:12:40 GMT
Domain 生成该 Cookie 的域名,如 domain="xulingbo.net"
Path 该 Cookie 是在当前的哪个路径下生成的,如 path=/wp-admin/
Secure 如果设置了这个属性,那么只会在 SSH 连接时才会回传该 Cookie


Set-Cookie2

属性项 属性项介绍
NAME=VALUE        与 Version 0 相同
Version 通过 Set-Cookie2 设置的响应头创建必须符合 RFC2965 规范,如果通过 Set-Cookie 响应头设置,默认值为 0,如果要设置为 1,则该 Cookie 要遵循 RFC 2109 规范
Comment 注释项,用户说明该 Cookie 有何用途
CommentURL 服务器为此提供的 URI 注释
Discard 是否在会话结束后丢弃该 Cookie 项,默认为 fasle
Domain 类似于 Version 0
Max-Age 最大失效时间,与 Version 0 不同的是这里设置的是在多少秒后失效
Path 类似于 Version 0
Port 该 Cookie 在什么端口下可以回传服务端,如果有多个端口,以逗号隔开,如 Port="80,81,8080"
Secure 类似于 Version 0

 

两个版本的 Cookie 中设置的 Header 头的标识符是不同的,我们常用的是 Set-Cookie:userName=“junshan”; Domain=“xulingbo.net”,这是 Version 0 的形式。针对 Set-Cookie2 是这样设置的:Set-Cookie2:userName=“junshan”; Domain=“xulingbo.net”; Max-Age=1000。但是在 Java Web 的 Servlet 规范中并不支持 Set-Cookie2 响应头,在实际应用中 Set-Cookie2 的一些属性项却可以设置在 Set-Cookie 中,如这样设置:Set-Cookie:userName=“junshan”; Version=“1”;Domain=“xulingbo.net”;Max-Age=1000。

 

当我们用如下方式创建 Cookie 时:

 

String getCookie(Cookie[] cookies, String key) { 
        if (cookies != null) { 
            for (Cookie cookie : cookies) { 
                if (cookie.getName().equals(key)) { 
                    return cookie.getValue(); 
                } 
            } 
        } 
        return null; 
    } 

    @Override 
    public void doGet(HttpServletRequest request, 
                      HttpServletResponse response) 
            throws IOException, ServletException { 
        Cookie[] cookies = request.getCookies(); 
        String userName = getCookie(cookies, "userName"); 
        String userAge = getCookie(cookies, "userAge"); 
        if (userName == null) { 
            response.addCookie(new Cookie("userName", "junshan")); 
        } 
        if (userAge == null) { 
            response.addCookie(new Cookie("userAge", "28")); 
        } 
        response.getHeaders("Set-Cookie"); 
 } 

 

Cookie 是如何加到 HTTP 的 Header 中的?当我们用 Servlet 3.0 规范来创建一个 Cookie 对象时,该 Cookie 既支持 Version 0 又支持 Version 1,如果您设置了 Version 1 中的配置项,即使您没有设置版本号,Tomcat 在最后构建 HTTP 响应头时也会自动将 Version 的版本设置为 1。

 

Session

 

前面介绍了 Cookie 可以让服务端程序跟踪每个客户端的访问,但是每次客户端的访问都必须传回这些 Cookie,如果 Cookie 很多,无形地增加了客户端与服务端的数据传输量,而 Session 的出现正是为了解决这个问题。

同一个客户端每次和服务端交互时,不需要每次都传回所有的 Cookie 值,而是只要传回一个 ID,这个 ID 是客户端第一次访问服务器的时候生成的,而且每个客户端是唯一的。这样每个客户端就有了一个唯一的 ID,客户端只要传回这个 ID 就行了,这个 ID 通常是 NANE 为 JSESIONID 的一个 Cookie。

 

那么Session 如何基于 Cookie 来工作?

 

有三种方式:

  • 基于 URL Path Parameter,默认支持。
  • 基于 Cookie,如果没有修改 Context 容器的 cookies 标识,默认也是支持的。
  • 基于 SSL,默认不支持,只有 connector.getAttribute("SSLEnabled") 为 TRUE 时才支持。

第一种情况下,当浏览器不支持 Cookie 功能时,浏览器会将用户的 SessionCookieName 重写到用户请求的 URL 参数中,它的传递格式如 /path/Servlet;name=value;name2=value2? Name3=value3,其中“Servlet;”后面的 K-V 就是要传递的 Path Parameters,服务器会从这个 Path Parameters 中拿到用户配置的 SessionCookieName。关于这个 SessionCookieName,如果在 web.xml 中配置 session-config 配置项,其 cookie-config 下的 name 属性就是这个 SessionCookieName 值。如果没有配置了 session-config 配置项,默认的 SessionCookieName 就是大家熟悉的“JSESSIONID”。需要说明的一点是,与 Session 关联的 Cookie 与其他 Cookie 没有什么不同。接着 Request 根据这个 SessionCookieName 到 Parameters 中拿到 Session ID 并设置到 request.setRequestedSessionId 中。

请注意,如果客户端也支持 Cookie,Tomcat 仍然会解析 Cookie 中的 Session ID,并会覆盖 URL 中的 Session ID。

如果是第三种情况,将会根据 javax.servlet.request.ssl_session 属性值设置 Session ID。

有了 Session ID 服务端就可以创建 HttpSession 对象了,第一次触发通过 request.getSession() 方法。如果当前的 Session ID 还没有对应的 HttpSession 对象,那么就创建一个新的,并将这个对象加到 org.apache.catalina. Manager 的 sessions 容器中保存。Manager 类将管理所有 Session 的生命周期,Session 过期将被回收,服务器关闭,Session 将被序列化到磁盘等。只要这个 HttpSession 对象存在,用户就可以根据 Session ID 来获取这个对象,也就达到了状态的保持。

分享到:
评论

相关推荐

    43_说说你们的分布式session方案是啥?怎么做的?.zip

    在Java开发中,常见的分布式Session实现方式有以下几种: 1. **Session复制**:这是一种简单的策略,即在集群中的每个节点都复制一份完整的Session数据。每当Session发生变化时,都会广播给其他节点。但是,这种...

    PHP实例开发源码—QQ空间说说自动抢一楼源码.zip

    这涉及到Cookie管理,可能使用到PHP的session和cookie函数,或者第三方库如HTTP_Request2,以保持会话状态。 4. **API接口调用**:QQ空间可能提供API供开发者使用,需要研究其API文档,了解如何通过API发送评论。...

    Python-QQ说说被点赞自动留言脚本

    3. **cookie和session**:登录成功后,服务器会返回cookie和session数据,用于后续的请求验证身份。Python的requests库能很好地处理这些,确保后续的HTTP请求携带正确的身份信息。 4. **JSON和API**:QQ空间的接口...

    ASP.NET简答题,doc文档

    **Cookie**主要分为两种类型:会话Cookie和持久性Cookie。 - **会话Cookie**:在用户浏览器关闭时自动删除,主要用于临时存储用户会话信息。 - **持久性Cookie**:具有有效期设置,在有效期内即使关闭浏览器也不会...

    值得收藏的2017年Java开发岗位面试题

    Servlet是Java Web开发的基础组件,用于处理客户端的请求。 3. webservice相关问题。 Webservice是基于SOAP协议的Web服务,用于提供远程方法调用。 4. jdbc连接,forname方式的步骤,怎么声明使用一个事务。 JDBC...

    java面试宝典

    22、我们在web 应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串? 10 23、String 和StringBuffer 的区别? 10 24、String, StringBuffer StringBuilder 的区别。 10 25、...

    超级有影响力霸气的Java面试题大全文档

    并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。 SessionBean在J2EE应用程序中被用来完成...

    java面试必会200题.docx

    7. **Cookie和Session的区别** - **Cookie**:存储在客户端浏览器上的小型文本文件,可用于跟踪用户信息。安全性较低,容量有限(通常不超过4KB)。 - **Session**:存储在服务器端的用户会话信息,安全性更高,...

    百度2019年最新面试题库

    #### Cookie和Session的区别 - **Cookie**: 存储在客户端的文本信息,常用于记录用户登录状态等信息。 - **Session**: 服务器端保存的信息,用于跟踪用户的活动。与Cookie相比,Session安全性更高,但会占用服务器...

    java面试题

    Web开发通常包括需求分析、设计、编码、测试、部署等阶段。 #### 说说你对框架的理解,为什么要用框架? 框架是一种提供基础架构和功能的软件平台,旨在简化应用开发过程,提高开发效率和代码质量。 #### 如何实现...

    33条C#、.Net经典面试题目及答案

    .NET平台是一个由微软提供的软件开发框架,旨在为开发人员提供一套完整的工具和API,用于创建各种类型的应用程序。它包括以下核心组成部分: - **CTS (Common Type System)**:公共类型系统,定义了所有.NET类型的...

Global site tag (gtag.js) - Google Analytics