session和cookie的区别

引言:cookie和session诞生的背景。

我们知道web浏览器和服务器在网络上传输通信的过程中是采用HTTP协议的,而HTTP协议是一种无状态的协议,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话,这个时候就要使用到会话跟踪技术了,那么什么是会话跟踪技术呢?会话是web应用中常见的技术,用来跟踪用户的整个会话过程,常见的会话跟踪技术就是cookie和session了,其中cookie通过在客户端记录信息从而确定用户的身份,而session是通过在服务器端记录信息从而确定用户的身份。

1. cookie会话机制

    Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该客户端用户的状态,就使用response返回向客 户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当客户端浏览器再次请求该网站时,客户端浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

Cookie是在客户端保持会话状态的方案。

     1.1 cookie的属性

         

cookie的属性包括名字,值,过期时间,路径和域,下面对属性进行相关的介绍:

Name: 该Cookie的名称。Cookie一旦创建,名称便不可更改

Value: 该Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码

Domain: 可以访问该Cookie的域名。如果设置为“.baidu.com”,则所有以“baidu.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”,不是"baidu.com"

Path: 该Cookie的使用路径。如果设置为“/xx/”,则只有contextPath为“/xx”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”

Expires/Max-Age:该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1

Secure: 该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false

1.2 Cookie的不可跨域名性

很多网站都会使用Cookie。例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。那浏览器访问Google会不会也携带上Baidu颁发的Cookie呢?或者Google能不能修改Baidu颁发的Cookie呢?

答案是否定的。Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。

Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作 Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名 不一样,因此Google不能操作Baidu的Cookie。

需要注意的是,虽然网站images.google.com与网站www.google.com同属于Google,但是域名不一样,二者同样不能互相操作彼此的Cookie。下面是Cookie的源代码。

package javax.servlet.http;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

public class Cookie implements Cloneable, Serializable {
    private static final long serialVersionUID = -6454587001725327448L;
    private static final String TSPECIALS;
    private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
    private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");
    private String name;
    private String value;
    private String comment;
    private String domain;
    private int maxAge = -1;
    private String path;
    private boolean secure;
    private int version = 0;
    private boolean isHttpOnly = false;

    public Cookie(String name, String value) {
        if (name != null && name.length() != 0) {
            if (this.isToken(name) && !name.equalsIgnoreCase("Comment") && !name.equalsIgnoreCase("Discard") && !name.equalsIgnoreCase("Domain") && !name.equalsIgnoreCase("Expires") && !name.equalsIgnoreCase("Max-Age") && !name.equalsIgnoreCase("Path") && !name.equalsIgnoreCase("Secure") && !name.equalsIgnoreCase("Version") && !name.startsWith("$")) {
                this.name = name;
                this.value = value;
            } else {
                String errMsg = lStrings.getString("err.cookie_name_is_token");
                Object[] errArgs = new Object[]{name};
                errMsg = MessageFormat.format(errMsg, errArgs);
                throw new IllegalArgumentException(errMsg);
            }
        } else {
            throw new IllegalArgumentException(lStrings.getString("err.cookie_name_blank"));
        }
    }

    public void setComment(String purpose) {
        this.comment = purpose;
    }

    public String getComment() {
        return this.comment;
    }

    public void setDomain(String domain) {
        this.domain = domain.toLowerCase(Locale.ENGLISH);
    }

    public String getDomain() {
        return this.domain;
    }

    public void setMaxAge(int expiry) {
        this.maxAge = expiry;
    }

    public int getMaxAge() {
        return this.maxAge;
    }

    public void setPath(String uri) {
        this.path = uri;
    }

    public String getPath() {
        return this.path;
    }

    public void setSecure(boolean flag) {
        this.secure = flag;
    }

    public boolean getSecure() {
        return this.secure;
    }

    public String getName() {
        return this.name;
    }

    public void setValue(String newValue) {
        this.value = newValue;
    }

    public String getValue() {
        return this.value;
    }

    public int getVersion() {
        return this.version;
    }

    public void setVersion(int v) {
        this.version = v;
    }

    private boolean isToken(String value) {
        int len = value.length();

        for(int i = 0; i < len; ++i) {
            char c = value.charAt(i);
            if (c < ' ' || c >= 127 || TSPECIALS.indexOf(c) != -1) {
                return false;
            }
        }

        return true;
    }

    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException var2) {
            throw new RuntimeException(var2.getMessage());
        }
    }

    public void setHttpOnly(boolean isHttpOnly) {
        this.isHttpOnly = isHttpOnly;
    }

    public boolean isHttpOnly() {
        return this.isHttpOnly;
    }

    static {
        if (Boolean.valueOf(System.getProperty("org.glassfish.web.rfc2109_cookie_names_enforced", "true")).booleanValue()) {
            TSPECIALS = "/()<>@,;:\\\"[]?={} \t";
        } else {
            TSPECIALS = ",; ";
        }

    }
}

1.3  Cookie的安全属性

HTTP协议不仅是无状态的,而且是不安全的。使用HTTP协议的数据不经过任何加密就直接在网络上传播,有被截获的可能。使用HTTP协议传输很机密的内容是一种隐患。如果不希望Cookie在HTTP等非安全协议中传输,可以设置Cookie的secure属性为 true。浏览器只会在HTTPS和SSL等安全协议中传输此类Cookie。下面的代码设置secure属性为true:

Cookie cookie = new Cookie("sex", "male"); // 新建Cookie

cookie.setSecure(true);                           // 设置安全属性

response.addCookie(cookie);                        // 输出到客户端

提示:secure属性并不能对Cookie内容加密,因而不能保证绝对的安全性。如果需要高安全性,需要在程序中对Cookie内容加密、解密,以防泄密。

2. session会话机制

     Session是另一种记录客户端用户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

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

package javax.servlet.http;

import java.util.Enumeration;
import javax.servlet.ServletContext;

public interface HttpSession {
    long getCreationTime();

    String getId();

    long getLastAccessedTime();

    ServletContext getServletContext();

    void setMaxInactiveInterval(int var1);

    int getMaxInactiveInterval();

    /** @deprecated */
    HttpSessionContext getSessionContext();

    Object getAttribute(String var1);

    /** @deprecated */
    Object getValue(String var1);

    Enumeration<String> getAttributeNames();

    /** @deprecated */
    String[] getValueNames();

    void setAttribute(String var1, Object var2);

    /** @deprecated */
    void putValue(String var1, Object var2);

    void removeAttribute(String var1);

    /** @deprecated */
    void removeValue(String var1);

    void invalidate();

    boolean isNew();
}

session运行原理:

浏览器第一次访问服务器时会创建一个session对象并返回一个JSESSIONID=ID的值,创建一个Cookie对象key为JSSIONID,value为ID的值,将这个Cookie写回浏览器。

浏览器在第二次访问服务器的时候携带Cookie信息JSESSIONID=ID的值,如果该JSESSIONID的session已经销毁,那么会重新创建一个新的session再返回一个新的JSESSIONID通过Cookie返回到浏览器。

session是基于Cookie技术实现,重启浏览器后再次访问原有的连接依然会创建一个新的session,因为Cookie在关闭浏览器后就会消失,但是原来服务器的Session还在,只有等到了销毁的时间会自动销毁。
一般这个值会有个时间限制,超时后毁掉这个值,默认30分钟。
当用户在应用程序的 Web页间跳转时,存储在 Session 对象中的变量不会丢失而是在整个用户会话中一直存在下去。
Session的实现方式和Cookie有一定关系。建立一个连接就生成一个session id,打开几个页面就好几个了,这里就用到了Cookie,把session id存在Cookie中,每次访问的时候将Session id带过去就可以识别了。

2.1  Session属性的相关介绍:

void setAttribute(String attribute, Object value):设置Session属性。value参数可以为任何Java Object。通常为Java Bean。value信息不宜过大

String getAttribute(String attribute):返回Session属性

Enumeration getAttributeNames():void removeAttribute(String attribute)

void removeAttribute(String attribute):移除Session属性

String getId():返回Session的ID。该ID由服务器自动创建,不会重复

long getCreationTime():返回Session的创建日期。返回类型为long,常被转化为Date类型,例如:Date createTime = new Date(session.get CreationTime())
long getLastAccessedTime():返回Session的最后活跃时间。返回类型为long

int getMaxInactiveInterval():返回Session的超时时间。单位为秒。超过该时间没有访问,服务器认为该Session失效

void setMaxInactiveInterval(int second):设置Session的超时时间。单位为秒

boolean isNew():返回该Session是否是新创建的

void invalidate():使该Session失效

3. 两者的区别

3.1 存储数据大小限制:session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象
3.2 存储地址不同(一个在客户端一个在服务端)。Cookie不安全,Session相对安全。
3.3 Session是保存在服务器端上会存在一段时间才会消失,如果session过多会增加服务器的压力
3.4 域的支持范围不一样,比方说a.com的Cookie在a.com下都能用,而www.a.com的Session在api.a.com下都不能用,解决这个问题的办法是JSONP或者跨域资源共享。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值