cookie

1、cookie基本介绍(客户端会话技术)

cookie 是存储在客户端的,即浏览器,所以称之为客户端会话技术。而 session 是存储在服务器端的,所以称之为服务器端会话技术。

cookie是纯文本,没有可执行代码,是指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端(浏览器)上的数据(通常经过加密)。当用户访问了某个网站的时候,我们就可以通过cookie在访问者电脑上存储数据,或者某些网站为了辨别用户身份、进行session 跟踪而将数据储存在用户本地终端上(通常经过加密)。

cookie 默认是临时存储的,当关掉浏览器时自动销毁(注意是关掉浏览器,如果只是关掉标签页,那cookie仍是存在的)。要想长时间保存一个cookie,就需要设置cookie的过期时间。当 Web 服务器创建了Cookies 后,只要在其有效期内,用户访问同一个 Web 服务器时(用户访问任何匹配该 Cookie 的路径和域的页面),浏览器首先要检查本地的Cookies,并将其原样发送给 Web 服务器。cookie是能保持 Web 浏览状态的手段。

 

1.1、浏览器查看cookie

在谷歌浏览器开发模式的 application 下可以看到某个页面所能访问到的 cookie。注意,只能看到该网页所能访问到的 cookie 数据,而不是浏览器所有的cookie。

 

 

2、cookie的工作过程

当网页要发 http 请求时,浏览器会先检查是否有相应的 cookie,有则自动添加在request header中的cookie字段中。这些是浏览器自动帮我们做的,而且每一次http请求浏览器都会自动帮我们做。

存储在cookie中的数据,每次都会被浏览器自动放在http请求中。如果这些数据并不是每个请求都需要发给服务端的数据,浏览器这设置自动处理无疑增加了网络开销。但如果这些数据是每个请求都需要发给服务端的数据(比如身份认证信息),浏览器这设置自动处理就大大免去了重复添加操作。所以对于那种设置“每次请求都要携带的信息(最典型的就是身份认证信息)”就特别适合放在cookie中,其他类型的数据就不适合了。

工作过程:

(1)首先,我们假设当前域名下还是没有 Cookie 的

(2)接下来,浏览器发送了一个请求给服务器(这个请求是还没带上 Cookie 的)

(3)服务器设置 Cookie 并发送给浏览器(当然也可以不设置)

(4)浏览器将 Cookie 保存下来

(5)接下来,以后的每一次请求,都会带上这些 Cookie,发送给服务器

 

3、cookie的相关概念

3.1、cookie的特点

  • 过期时间:cookie 默认是存放在浏览器内存的,所以当会话结束(关闭浏览器)的时候即销毁当然也可以手动设置过期的时间,此时cookie将会被写到硬盘的文件中,,持久化存储,当时间到期才自动销毁。
  • 域:默认是当前页面所在的域名。我们可以设置cookie生效的域(当前设置cookie所在域的子域),也就是说,我们能够操作的cookie是当前域以及当前域下的所有子域
  • path:默认是当前项目的虚拟目录。
  • 容量:一个浏览器能创建的 Cookie 数量最多为 300 个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个
  • 安全性:因为cookie本身是存储在浏览器端的,所以并不安全,并且容量有限,所以只适用于存储少量的不太敏感的信息。
  • cookie的存储是以域名形式进行区分的,在同一浏览器下不同的域名下存储的cookie是独立的。不同的浏览器存放的cookie位置不一样,也是不能通用的。
  • cookie 必须在 HTML 文件的内容输出之前设置。如果用户在浏览器上设置了禁止 Cookie,则 Cookie 不能建立。

 

3.2、cookie的过期时间

cookie 默认是存放在浏览器内存的,所以当会话结束(关闭浏览器)的时候即销毁当然也可以手动设置过期的时间,此时cookie将会被写到硬盘的文件中,持久化存储,当时间到期才自动销毁。

 

3.3、cookie的域(domain)

domain 默认值是当前页面所在的域名。domain 指定了 cookie 将要被发送至哪个或哪些域中。默认情况下,domain 会被设置为创建该 cookie 的页面所在的域名,所以当给相同域名发送请求时该 cookie 会被发送至服务器。浏览器会把 domain 的值与请求的域名做一个尾部比较(即从字符串的尾部开始比较),并将 domain 能匹配到域名的 cookie 发送至服务器。

(1)客户端设置

document.cookie = "username=cfangxu;path=/;domain=qq.com" 

上面将 domain 设置为 qq.com,即一级域名,表示访问域名尾部是 qq.com 的网站时浏览器都会将该 cookie 带上。path 值为 "/" 表示访问 qq.com 域名下的根目录下的都将能带上该 cookie。

(2)服务端设置

Set-Cookie: username=cfangxu;path=/;domain=qq.com 
// 注:一定的是同域之间的访问,不能把domain的值设置成非主域的域名。

 

3.4、cookie的路径(path)

path 默认是当前前端项目的虚拟目录。比如:http://localhost:8080/javawebtest02_war_exploded/test/test01.jsp ,javawebtest02_war_exploded是项目名,则path为javawebtest02_war_exploded。

因为安全方面的考虑,默认情况下,只有与创建 cookie 的页面在同一个目录或子目录下的网页才可以访问。但 path 属性可以为 cookie 指定路径,domain 和 path 加起来构成了URL,表示当浏览器在访问该 URL 下的网站或者 URL 带有这个前缀的网站时都将会带上该 cookie 。

(1)客户端设置

 最常用的例子就是让 cookie 在根目录下,这样不管是哪个子页面创建的 cookie,该域名下的所有页面都可以访问到了。

document.cookie = "username=cfangxu; path=/"

(2)服务器端设置

Set-Cookie:name=cfangxu; path=/blog

如上设置:path 选项值会与 /blog,/blogrool 等等相匹配;任何以 /blog 开头的选项都是合法的。需要注意的是,只有在 domain 选项核实完毕之后才会对 path 属性进行比较。path 属性的默认值是发送 Set-Cookie 消息头所对应的 URL 中的 path 部分。

 

3.5、domain和path的关系(domain+path=URL)

domain是域名,path是路径,两者加起来就构成了 URL,domain和path一起来限制 cookie 能被哪些 URL 访问。 

所以domain和path两个选项共同决定了cookie何时被浏览器自动添加到请求头部中发送出去。如果没有设置这两个选项,则会使用默认值。domain的默认值为设置该cookie的网页所在的域名,path默认值为设置该cookie的网页所在的目录。

 

4、JS操作cookie

JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 cookie。

浏览器端可以设置cookie 的下列选项:expires、domain、path、secure(有条件:只有在https协议的网页中,客户端设置secure类型的 cookie 才能成功),但无法设置HttpOnly选项。

 

4.1、创建cookie

document.cookie="username=John Doe";

添加过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";

添加浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

4.2、读取cookie

 通过document.cookie来获取当前网站下的cookie的时候,得到的是字符串形式的值,它包含了当前网站下所有的cookie,这个方法只能获取非 HttpOnly 类型的cookie。它会把所有的cookie通过一个分号+空格的形式串联起来,例如:username=chenfangxu; job=coding

var x = document.cookie;

4.3、修改 cookie

要想修改一个cookie,只需要重新赋值就行,旧的值会被新的值覆盖。但要注意一点,在设置新cookie时,path/domain这几个选项一定要旧cookie 保持一样。否则不会修改旧值,而是添加了一个新的 cookie。

document.cookie="username=John Smith; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

4.4、删除 cookie

把要删除的cookie的过期时间设置成已过去的时间,path/domain/这几个选项一定要旧cookie 保持一样。

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

 

5、Java操作cookie

服务端可以设置cookie 的所有选项:expires、domain、path、secure、HttpOnly。

 

5.1、设置并返回cookie

  • 设置cookie:Cookie cookie = new Cookie("key", "value");
  • 给浏览器返回cookie:response.addCookie(cookie);  即发送 Cookie 到 HTTP 响应头
  • 读取浏览器发送的cookie:Cookie[] cookies = request.getCookies();

代码示例:

@WebServlet("/cookieTest01")
public class CookieTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //读取客户端发送的cookie
        Cookie[] cookies = req.getCookies();
        if(cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                String name = cookies[i].getName();
                String val = cookies[i].getValue();
                System.out.println(name + ": " + val);
            }
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置cookie。可以一次性添加多个cookie,只需重复下面操作先创建然后添加至response即可
        Cookie cookie = new Cookie("cookieTest","cookieTestValue");
        //给客户端返回cookie
        response.addCookie(cookie);
    }
}

当我们设置了 cookie,并且给客户端返回时,在浏览器的可以看到该请求的响应头上有 set-cookie 头信息。在设置了多个cookie时,每个cookie将以分号 ; 分隔开。

 

浏览器获取到 set-cookie 响应头时就会自动给浏览器添加 cookie 信息,并且在下次发出请求时会自动把 cookie 信息给带上,如下:

 

5.1.1、cookie中存取中文

在 tomcat8 之后的版本,可以直接往 cookie 中存储中文数据。但在 tomcat8 之前,cookie 是不能直接存储中文的,所以我们需要将中文数据先编码然后放在cookie当中,在从浏览器中拿取时,也需要先解码后才能拿到正确数据。

我们可以采用 URL 编码来对中文数据进行编码:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String cookieStr = java.net.URLEncoder.encode("cookie的中文值","UTF-8")  //将中文数据编码后再放入cookie
        Cookie cookie = new Cookie("cookieTest", cookieStr);
        response.addCookie(cookie);
}

在读取cookie时,可以使用 URL 解码:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("读取cookie:");
        Cookie[] cookies = req.getCookies();
        if(cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                String name = cookies[i].getName();
                String val = cookies[i].getValue();

                System.out.println(name + ": " + java.net.URLDecoder.decode(val,"UTF-8"));  //使用java.net.URLDecoder.decode() 进行解码
            }
        }
}

 

5.2、设置cookie的过期时间

通过 setMaxAge(int 秒数) 方法可以设置 cookie 过期的时间(以秒为单位),该方法指定了该 cookie 将在指定的秒数时间过后被销毁。如果不这样设置,cookie 只会在当前 session 会话中持续有效。

public void setMaxAge(int 秒数);

setMaxAge() 方法的参数可以是正数、负数、0。当为正数时,表示指定秒数过后该 cookie 被自动销毁;当为负数时,表示 cookie 的过期时间为默认值,即浏览器关闭时;当为0时,表示删除该 cookie。

 

代码示例:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("cookieName","cookieValue");
        cookie.setMaxAge(30);
        resp.addCookie(cookie);
}

上面设置了过期时间时,可以看到响应头 set-cookie 里有指定该cookie的过期时间:

我们指定了30秒,在30秒过后你可以看到该 cookie 在浏览器中会被自动销毁,此时在浏览器往服务器发请求时也不会带上该 cookie。但是在 30 秒之内,就算关闭了浏览器,此时该 cookie 仍是存在的,在浏览器往服务器发请求时也是会带上该 cookie 的。

 

5.3、删除cookie

服务器端可以通过以下方法来删除浏览器端的 cookie,实际上是设置该 cookie 的过期时间为0。

步骤如下:

  1. 读取一个现有的 cookie
  2. 使用 setMaxAge(0) 方法将该cookie的过期时间设为0
  3. 把这个 cookie 添加到响应头

 

代码示例:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //读取浏览器发送的全部cookie
        Cookie[] cookies = request.getCookies();
        if(cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                if(cookies[i].getName().equals("cookieName")) {
                    cookies[i].setMaxAge(0);   //设置该 cookie 的过期时间为0,即删除该cookie
                    response.addCookie(cookies[i]);  //将该cookie添加至响应消息,浏览器将自动删除该cookie
                }
            }
        }
}

在请求上面servlet时,服务器将会返回该cookie,同时将该cookie的过期时间设为0,此时浏览器将会自动将该cookie在浏览器端删除。

 

5.4、设置cookie的path

cookieObj.setPath() 方法可设置cookie的path。如果不指定路径,则 path 的值为当前页面的项目的虚拟目录。比如:http://localhost:8080/javawebtest02_war_exploded/test/test01.jsp ,javawebtest02_war_exploded是项目名,则path为javawebtest02_war_exploded。

public void setPath(String uri)

我们可以使用 cookieObj.setPath("/"); 来设置该 cookie 在当前页面的域名下的所有页面都可访问该 cookie。

 

posted @ 2019-03-04 14:57  wenxuehai  阅读(7563)  评论(0编辑  收藏  举报
//右下角添加目录