JavaWeb 之 Cookie

Cookie 

一、会话概述

  1、会话:一次会话中包含多次请求和响应。

        一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止。

Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求。

  2、功能

    在一次会话的范围内的多次请求间,共享数据

  3、方式

    客户端会话技术:Cookie

    服务器端会话技术:Session

二、Cookie 概述

  1、Cookie 是客户端会话技术,将数据保存到客户端,是服务器通知客户端保存键值对的一种技术;

  2、客户端有了 Cookie 后,每次请求都发送给服务器;

  3、每个 Cookie 的大小不能超过 4KB;

三、Cookie 的使用

  1、创建 Cookie 对象

    Cookie 的 JDK 已经内置好的一个对象,可以通过构造方法直接来创建 cookie 对象;

    构造方法:

Cookie cookie = new Cookie(String name,String value);

      创建一个 Cookie 对象,name 表示 cookie 的值,value表示 cookie 里面存放的值。

     使用 response 对象可以将 cookie 发送到客户端

    发送方法:

response.addCookie(Cookie cookie) 

    原理图:

    

     代码示例:

 1 protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 2         //1 创建 Cookie 对象
 3         Cookie cookie = new Cookie("key1", "value1");
 4         //2 通知客户端保存 Cookie
 5         resp.addCookie(cookie);
 6         //1 创建 Cookie 对象
 7         Cookie cookie1 = new Cookie("key2", "value2");
 8         //2 通知客户端保存 Cookie
 9         resp.addCookie(cookie1);
10         resp.getWriter().write("Cookie 创建成功");
11     }

    注意

      ① 可以同时创建多个 cookie 对象,但是一定要用 addCookie() 方法设置到响应里;

      ② cookie() 不能包含中文和特殊字符,值不应包含空格、方括号、圆括号、等号、逗号、双引号、斜杠、问号、at 符号、冒号和分号。空值在所有浏览器上的行为不一定相同。

  2、服务器获取 Cookie

    在服务器获取客户端的 Cookie,需要使用 HttpServletRequest 的方法:

Cookie[] request.getCookies():获取客户端所有的 cookie 对象
String getName() 获取某个 cookie的 key(名)
String getValue() 获取某个 cookie的 value(值)

      原理图:

    

    代码示例:

     把根据名称查找 Cookie 抽取成工具类:

 1  public class CookieUtils {
 2         /**
 3          * 查找指定名称的 Cookie 对象
 4          * @param name
 5          * @param cookies
 6          * @return
 7          */
 8         public static Cookie findCookie(String name , Cookie[] cookies){
 9             if (name == null || cookies == null || cookies.length == 0) {
10                 return null;
11             } 
12             for (Cookie cookie : cookies) {
13                 if (name.equals(cookie.getName())) {
14                     return cookie;}
15             } 
16             return null;
17         }
18     }

     获取 Cookie: 

 1 protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 2         Cookie[] cookies = req.getCookies();
 3         for (Cookie cookie : cookies) {
 4         // getName 方法返回 Cookie 的 key(名)
 5         // getValue 方法返回 Cookie 的 value 值
 6             resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "] <br/>");
 7         } 
 8         Cookie iWantCookie = CookieUtils.findCookie("key1", cookies);
 9 
10         // 如果不等于 null, 说明赋过值, 也就是找到了需要的 Cookie
11         if (iWantCookie != null) {
12             resp.getWriter().write("找到了需要的 Cookie");
13         }
14     }

  3、Cookie 值的修改

    方案一:

      ① 先创建一个要修改的同名(key)的 Cookie 对象;

      ② 在构造器中,同时赋于新的 Cookie 的值;

      ③ 调用 response.addCookie(Cookie);

    代码示例:

1         // 1、 先创建一个要修改的同名的 Cookie 对象
2         // 2、 在构造器, 同时赋于新的 Cookie 值。
3         Cookie cookie = new Cookie("key1","newValue1");
4         // 3、 调用 response.addCookie( Cookie ); 通知 客户端 保存修改
5         resp.addCookie(cookie);

    方案二:

      ① 先查找到需要修改的 Cookie 对象;

      ② 调用 setValue() 方法赋于新的 Cookie 值;

      ③ 调用 response.addCookie() 通知客户端保存修改;

    代码示例:

1    // 1、 先查找到需要修改的 Cookie 对象
2     Cookie cookie = CookieUtils.findCookie("key2", req.getCookies());
3     if (cookie != null) {
4         // 2、 调用 setValue()方法赋于新的 Cookie 值。
5         cookie.setValue("newValue2");
6         // 3、 调用 response.addCookie()通知客户端保存修改
7         resp.addCookie(cookie);
8     }

三、使用浏览器查看 Cookie

  1、谷歌浏览器查看 Cookie

    

  2、火狐浏览器查看 Cookie

    

四、实现原理

  Cookie 基于响应头 set-cookie 和请求头 cookie 实现的。

  原理示意图:

  

   第一次访问服务器时,服务器就会给浏览器一个 “身份识别卡”,浏览器每次向服务器发送请求时都会带着这个 “身份识别卡”,当服务器看到这个 卡片时就可以识别浏览器的身份。

   实际上这个 “身份识别卡” 就是服务器发送的一个响应头:

   

   如上图 Set-Cookie 这个响应头就是服务器在向浏览器发送的 “身份识别卡”,这个响应头名字是 Set-Cookie,后面的 JSESSIONID=95A92EC1D7CCB4ADFC24584CB316382E 和 Path=/Test_cookie,是两组键值对的结构就是服务器为这个“身份识别卡”设置的信息。浏览器收到该信息后就会将它保存到内存或硬盘中。

   当浏览器再次向服务器发送请求时就会携带这个 Cookie 信息:

   

    这是浏览器发送的请求报文,中间画红框的就是 Cookie 信息,即浏览器带着“身份识别卡”访问服务器,服务器就可以根据 Cookie 信息来判断浏览器的状态。

五、Cookie 生命控制(有效性)

   Cookie 是存储在浏览器中的,但是一般情况下浏览器不可能永久保存一个 Cookie,一是占用硬盘空间,二是 Cookie 可能只在某一时刻有用没必要长久保存。

   Cookie 的生命控制指的是如何管理 Cookie 什么时候被销毁(删除)

   可以通过下面的方法来进行设置:

setMaxAge()设置 Cookie 的最大生存时间以秒为单位
    正数:表示在指定的秒数后过期
    负数:意味了 cookie 不会被持久存储,表示浏览器一关,Cookie 就会被删除
    零:Cookie 立即失效,表示马上删除 Cookie,下次浏览器发送请求将不会携带该 Cookie
   不设置:默认值是 -1,则默认当前会话有效,关闭浏览器失效。(会话级别)

  

六、Cookie 有效路径 Path的设置

  Cookie 的 Path 属性可以有效的过滤哪些 Cookie 可以发送给服务器,哪些不发送。

  通过Cookie的 setPath() 来设置路径,这个路径是由浏览器来解析的所以/代表服务器的根目录,如果不设置,默认在访问 “/项目名” 下的资源时携带。

  path 属性是通过请求的地址来进行有效的过滤。

  图解:

  

  Demo:

1 protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
2         Cookie cookie = new Cookie("path1", "path1");
3         // getContextPath() ===>>>> 得到工程路径
4         cookie.setPath( req.getContextPath() + "/abc" ); // ===>>>> /工程路径/abc
5         resp.addCookie(cookie);
6         resp.getWriter().write("创建了一个带有 Path 路径的 Cookie");
7     }

五、Cookie 细节

  1、一次可不可以发送多个 cookie?

     可以一次发送多个cookie对象。

     可以创建多个 cookie 对象,使用 response 调用多次 addCookie 方法发送 cookie 即可。

  2、cookie 在浏览器中保存多长时间?

    (1)默认情况下,当浏览器关闭后,cookie 数据被销毁

    (2)持久化存储

setMaxAge(int seconds)  // 单位为秒

       ① 正数:将 cookie 数据写到硬盘的文件中。持久化存储,并指定 cookie 存活时间,时间到了,cookie 文件自动失效;

        ② 负数:默认值,关闭浏览器 cookie 销毁;

        ③ :删除当前的 cookie 信息;

  3、cookie 是否能够存储中文

    (1)在 Tomcat 8 之前,cookie 中不能直接存储中文数据。

       如果需要将中文数据转码(一般采用 URL 编码)

    (2)在 Tomcat 8 之后,cookie 支持中文数据。

          但是对特殊字符(如:空格等)还是不支持,建议使用 URL 编码存储,用URL解码解析。

  4、cookie 共享问题?

    假设在一个 Tomcat 服务器中,部署了多个 web 项目,那么在这些 web 项目中 cookie 能不能共享?

     默认情况下 cookie 不能共享。

     解决方法:

setPath(String path)

      使用上面的方法可以实现 cookie 共享,设置 cookie 的获取范围。默认情况下,设置当前的虚拟目录。

      如果要在一个服务器间共享,则可以将 path 设置为"/" ,代表一个服务器内都可以共享。

  5、不同的 tomcat 服务器 cookie 之间如何共享?

setDomain(String path);

      通过设置该方法,如果设置一级域名相同,那么多个服务器之间cookie可以共享。

    Demo:

setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

  

六、Cookie 的特性

  1、特点

    (1)cookie 存储数据在客户端浏览器,不安全,容易被篡改

    (2)浏览器对于单个 cookie 的大小由限制(4KB左右),而且对同一个域名下的总 cookie 的数量也有限制(20个)

  2、作用

    (1)cookie 一般用于存储少量的不太敏感的数据;

    (2)在不登录的情况下,完成服务器对客户端的身份识别;

  3、缺点

    (1)Cookie 是为请求或响应报文发送,无形中增加了网络流量;

    (2)Cookie 是明文传送的安全性差;

    (3)各个浏览器对 Cookie 有限制,使用上有限制;

原文地址:https://www.cnblogs.com/niujifei/p/11622456.html