`
MauerSu
  • 浏览: 513152 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Session 与 Cookie

 
阅读更多

源:http://www.blogjava.net/fancydeepin/archive/2013/10/02/cookie_and_session.html

评:

HTTP 协议 ( 超文本传输协议 ) 是无状态的,不能保存客户端与服务器之间通讯 ( 交互 ) 的信息。
打个比方,拿最常见的登录来说,现在好多网站的操作都需要用户登录,假如在 a 操作时,用户成功登录系统,再进行 b 操作时,由于 HTTP 协议是无状态的,
用户之前登录的信息并没有被记录下来。那么,用户需要再次登录系统才能继续操作,以此类推,每个操作都需要登录一次系统,这是非常可怕的事情。
cookie 和 session 技术的诞生,都是为解决 HTTP 无状态协议所带来的系列问题。它们可以维护用户与服务器间的会话状态。

Cookie

cookie 是保存在客户端的文本文件。在这个文本文件中以键值对 ( key - value ) 的形式保存了一些与用户相关的信息,如常见的有账号信息等。


package fan.commons.web;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * Cookie 操作
 * @Author fancy
 * @Mail fancore@126.com
 * @Date 2013-09-29
 
*/
public class Cookies {
    
    private final HttpServletRequest request;
    private final HttpServletResponse response;
    
    public Cookies(final HttpServletRequest request, final HttpServletResponse response){
        this.request = request;
        this.response = response;
    }
    
    /**
     * 添加Cookie
     * 
@param cookie 实例
     
*/
    public void add(Cookie cookie){
        response.addCookie(cookie);
    }
    
    /**
     * 添加Cookie
     * 
@param name  名称
     * 
@param value 值
     
*/
    public void add(String name, String value){
        add(name, value, -1);
    }
    
    /**
     * 添加Cookie
     * 
@param name  名称
     * 
@param value 值
     * 
@param secondTimeout 设定多少秒后过期。若为负数, 则浏览器关闭后Cookie失效。
     
*/
    public void add(String name, String value, int secondTimeout){
        Cookie cookie = new Cookie(name, value);
        cookie.setMaxAge(secondTimeout);
        cookie.setPath("/");
        response.addCookie(cookie);
    }
    
    /**
     * 根据名称获取Cookie对象。如果不存在则返回null。
     * 
@param name 名称
     * 
@return 返回Cookie对象
     
*/
    public Cookie getCookie(String name){
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for(Cookie cookie : cookies){
                if(cookie.getName().equals(name)){
                    return cookie;
                }
            }
        }
        return null;
    }
    
    /**
     * 根据名称获取Cookie对象的值。如果不存在则返回null。
     * 
@param name  名称
     * 
@return  返回该Cookie对象的值
     
*/
    public String getValue(String name){
        Cookie cookie = getCookie(name);
        return cookie == null ? null : cookie.getValue();
    }
    
    /**
     * 删除Cookie
     * 
@param name 名称
     
*/
    public void delete(String name){
        delete(new Cookie(name, null));
    }
    
    /**
     * 删除Cookie
     * 
@param cookie 需要删除的对象
     
*/
    public void delete(Cookie cookie){
        cookie.setMaxAge(0);  //0表示立即删除
        cookie.setPath("/");
        response.addCookie(cookie);
    }
    
    /**
     * 清空Cookie
     
*/
    public void clear(){
        Cookie[] cookies = request.getCookies();
        if(cookies != null){
            for(Cookie cookie : cookies){
                delete(cookie);
            }
        }
    }
}

public class CookieServlet extends HttpServlet {

    protected void service(HttpServletRequest request, HttpServletResponse response) {
        Cookies cookie = new Cookies(request, response);
        if(cookie.getValue("username") == null){
            cookie.add("username", "fancy");
        }
        //从客户端传递过来的 cookie 中获取信息
        System.out.println(cookie.getValue("username"));
    }

}



当客户端发起 http 请求时,相关的 cookie 信息将被放在 http 请求头 ( Request Headers ) 中,并发送至服务器端。
当服务器向客户端写回 ( 新建、更新、删除 ) cookie 时,这些 cookie 信息将被放到 http 响应头 ( Response Headers ) 中,并发回给客户端浏览器。
客户端浏览器接收并解析服务器发回的 cookie 信息,然后将它保存到文件或保存到内存当中。




Session

Session 是保存在服务器端,用于存放一些与用户相关的信息,如登录状态等。

Session 的创建时机

首先,Session 不是在客户机首次访问服务器时被创建的。
Session 的创建时机是当服务器端程序首次执行 HttpServletRequest.getSession() 或 HttpServletRequest.getSession(true) 时被创建的。
HttpServletRequest.getSession() 和 HttpServletRequest.getSession(true) 是等效的,
调这两个方法的时候,若 Session 已经存在,则直接返回使用。若不存在,则创建一个 Session 对象并返回使用。
HttpServletRequest.getSession(false) ,调用该方法的时候,若 Session 已经存在,则返回使用。若不存在,则返回 null。
下面借助 Session 监听器来监听 Session 的创建时机:

package fan.core.listener;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class SessionListener implements HttpSessionListener {
    
    public SessionListener(){
        System.out.println("*******************************");
        System.out.println("Startup SessionListener");
        System.out.println("*******************************");
    }

    public void sessionCreated(HttpSessionEvent e) {
        System.out.println("*******************************");
        System.out.println("Create Session");
        System.out.println("*******************************");
    }

    public void sessionDestroyed(HttpSessionEvent e) {
        System.out.println("*******************************");
        System.out.println("Destroy Session");
        System.out.println("*******************************");
    }

}

public class TestServlet extends HttpServlet {

    protected void service(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("*******************************");
        System.out.println("TestServlet");
        System.out.println("*******************************");
    }

}

<listener>
  <listener-class>fan.core.listener.SessionListener</listener-class>
</listener>

<servlet>
  ......
</servlet>

访问 TestServlet,发现控制台并没有打印出 "Create Session"。
修改 TestServlet 代码如下:

public class TestServlet extends HttpServlet {

    protected void service(HttpServletRequest request, HttpServletResponse response) {
        request.getSession(true);
    }

}

再次访问该 TestServlet,控制台打印出 "Create Session"。

重启服务器,在浏览器中首次访问服务器中的任一 JSP 资源,发现控制台也打印出 "Create Session"。这是怎么回事呢?
是这样的,JSP 引擎在将 JSP 文件编译成类 Servlet 类文件 ( 该文件可以在 %Tomcat%/work/%工程目录% 下找到 ) 时,还是打开 index_jsp.java 源码来对照着说吧:



可以看到源码中有一行 session = pageContext.getSession()。
这里的 pageContext 是 org.apache.jasper.runtime.PageContextImpl 的一个实例 ( 这个验证非常简单,有兴趣的可以动手试试 ),
打开 PageContextImpl 源码看一眼:



可以看到,JSP 默认的实现方式中去调了 HttpServletRequest.getSession() 方法,因此,当第一次访问某个 JSP 文件时,
如果服务器之前还没有为该用户创建过 Session,则会创建一个,而不管 Session 会不会被用到。
这里可以通过 <%@page session="false"%> 来关闭 JSP 中默认创建 Session 的行为。
当在 jsp 文件中设置 <%@page session="false"%>,访问这个 jsp 文件,如 index.jsp,那么再打开 index_jsp.java 文件,
发现 session = pageContext.getSession() 这一行不见了,控制台也没有打印出 "Create Session" 的字样。

JSESSIONID ( session cookie / sessionid )

同一时间里,服务器端存在许多 Session 对象。假如一个 Session 对象代表一个用户,那么,当某客户机请求服务器时,服务器如何知道哪个 Session 属于 哪个用户呢?
这是通过唯一标识 id 来识别的。服务器首先检查客户端请求里是否包含 session 标识,如果已经包含,说明服务器之前已经为该用户创建了 session,接着服务器根据这个 session 标识去检索对应的 session 对象。如果检索不到 (可能因为 session 过期已被销毁),则可能创建一个新的 session 对象 (HttpServletRequest.getSession(false) 的时候不创建)。如果客户端请求里不包含 session 标识,则创建一个新的 session 对象。服务器在创建 session 对象的时候会为每个 session 对象关联一个唯一的标识 sessionid,并将该标识的值以 cookie 的方式写回给客户端浏览器,保存在客户端浏览器内存中。当客户端再次向服务器发起请求时,根据 HTTP 协议,cookie 会被携带到服务器端,而 cookie 里面保存了一个能唯一标识用户自己身份的 sessionid,服务器端根据这个 id 就能找得到属于用户自己的 session 了。
从上面描述可以知道,session 是基于 cookie 机制来实现的,因此,上面所提到的 session 标识、sessionid 通常被称为 session cookie。我们平常时候所说的 cookie 被称为 persistent cookie。session cookie 是保存在客户端浏览器的内存当中,仅在本次会话中有效,当浏览器关闭之后,session cookie 也就失效并随之消失了。
cookie 是通过键值对 ( Key-Value ) 的形式来保存文本信息的,在 Java Web 运用中,session cookie 的键的名称为 JSESSIONID。看到 JSESSIONID,相信很多人都有一种亲切感,一般情况下,通常我们是看不到 JSESSIONID 的,因为它保存在 cookie 中,每次随请求默默的发送至服务器端。

修改 SessionListener 的 sessionCreated 方法:

public void sessionCreated(HttpSessionEvent e) {
    System.out.println("*******************************");
    System.out.println("Create Session, id = " + e.getSession().getId());
    System.out.println("*******************************");
}

public class TestServlet extends HttpServlet {

    protected void service(HttpServletRequest request, HttpServletResponse response) {
        request.getSession(true);
    }

}

访问 TestServlet,结果如图:



public class TestServlet extends HttpServlet {

    protected void service(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession(true);
        System.out.println("[ Session ] " + session.getId());
        Cookies cookies = new Cookies(request, response);
        System.out.println("[ Cookies ] " + cookies.getValue("JSESSIONID"));
    }

}



据说,在客户端禁用 cookie 的环境下,服务器会通过 URL 重写的方式,将 JSESSIONID 作为参数传递到服务器端。
本人不才,用了好些个浏览器禁用 cookie 几经折腾,并没有发现目标 URL 被重写,也没有发现请求参数中含有 JSESSIONID。什么情况? 

 Session 销毁的时机

当 session 有效期已过或服务器端程序调用了 HttpSession.invalidate(),则 session 对象被销毁,session 的内存空间也随之被 GC 收回。
客户端关闭浏览器时,存储在服务器端的 session 并不会被立刻销毁,直到 session 有效期过了,服务器才来销毁 session 对象。

Session 与浏览器的关系

根据上面对 JSESSIONID 的阐述,客户端浏览器每次请求服务器时,都会将能唯一识别用户 session 的 JSESSIONID 携带至服务器,以作为用户识别的身份凭据。
另外也知道,JSESSIONID 是保存在客户端浏览器的 cookie 文件中,存储在浏览器内存当中,其生命周期与浏览器相同。当多个浏览器请求同一台服务器时,在首次请求中,服务器发现这些浏览器都没有携带能标识用户 Session 的 JSESSIONID,因此,服务器分别为这些浏览器创建一个 Session 对象,并通过 HTTP 的响应头消息将 Session 的 id 以 cookie 的方式写回给客户端浏览器。因此,不同的浏览器所使用的 session 是不一样的 ( 这里只针对一般的情况 )。




   [ 随笔均原创,转载请注明出处:http://www.blogjava.net/fancydeepin ]

分享到:
评论

相关推荐

    关于session与cookie的原理简述

    【Session与Cookie原理简述】 Session和Cookie是两种在Web开发中常见的用户状态管理机制,它们主要用于在HTTP协议无状态的特性下跟踪用户状态。理解它们的原理对于编写高效的Web应用至关重要。 **Cookie原理** ...

    session与cookie的区别和联系?

    ### Session与Cookie的区别和联系 #### 一、概念解析 - **Cookie**:Cookie是一种小型的数据文件,由服务器端生成并发送给用户浏览器,浏览器在本地(如用户的硬盘)保存该文件,然后每一次请求同一网站时都会把该...

    session与cookie

    **二、会话Cookie与持久Cookie的区别** 1. **会话Cookie**:若未设置过期时间,Cookie生命周期仅限于当前浏览器会话,关闭浏览器窗口后即消失,不保存在硬盘上。 2. **持久Cookie**:设置过期时间的Cookie会被保存...

    session与cookie的区别以及配置使用

    #### 二、Cookie与Session简介及区别 **Cookie** 是一种简单的文本文件,用于在客户端存储少量数据。它允许网站保存用户的信息以便后续访问时能够快速获取。例如,网站可以通过Cookie来记住用户的登录状态。 **...

    session与cookie区别精选

    session与cookie区别精选,session与cookie区别精选,session与cookie区别精选,session与cookie区别精选session与cookie区别精选session与cookie区别精选session与cookie区别精选session与cookie区别精选session与...

    session与cookie的内容.doc

    **Session与Cookie** Session和Cookie是Web开发中用于管理用户状态的两种常见技术。它们的主要区别在于数据存储的位置和安全性。 - **Session**: Session将用户的相关信息存储在服务器端,通常是一个键值对的集合...

    PHP会话控制SESSION与COOKIE

    SESSION与COOKIE的主要区别在于数据存储位置和安全性。SESSION数据存储在服务器,相对更安全,不会被客户端直接访问;而COOKIE存储在用户端,容易受到篡改或盗窃。此外,SESSION在服务器端消耗资源,当并发用户多时...

    session与cookie相同点和不同点

    session与cookie相同点和不同点

    session与cookie的区别?

    session与cookie的区别?

    第六章ApplicationSession与Cookie对象.ppt

    【第六章 Application、Session与Cookie对象】 在ASP.NET开发中,Application、Session和Cookie对象是三个重要的概念,它们主要用于在用户交互过程中管理数据和状态。本章将详细讲解这三个对象的功能、使用方法以及...

    6.4: Session与Cookie 、 部署memcached 、 Session共享 、 .docx

    总结,理解Session与Cookie的区别、部署Memcached实现Session共享,以及如何在Linux环境中配置LNMP服务器是Web开发和运维中的重要技能。在实际应用中,需要根据业务需求选择合适的技术,并优化配置,确保系统的稳定...

    session与cookie区别ppt

    session与cookie区别课件,可以下载根据自己的需求改动,节省整理的时间

    session与cookie详解

    关于session和cookie的详细解释 &lt;br&gt;所有疑问通吃

    session与cookie.doc的区别

    Session和Cookie是两种常见的Web应用程序中用于管理用户会话的技术,它们主要的区别在于存储位置、生命周期和安全性。 **Session** 1. **存储位置**:Session是服务器端存储机制,它在服务器上为每个用户开辟一块...

    TOMCAT中SESSION与COOKIE的深度探索.pdf

    TOMCAT中SESSION与COOKIE的深度探索.pdf

    Session与Cookie

    上JSP老师的代码,关于回话session与cookie的比较代码

    asp.net的session和cookie的应用

    与Session不同,Cookie存储在客户端,这意味着它们可以在用户关闭和重新打开浏览器后仍然存在,但容量有限,一般不超过4KB。Cookie通常用于存储登录状态、用户首选项等不敏感信息。 创建Cookie也很直观,比如`...

Global site tag (gtag.js) - Google Analytics