cookie&session(上)

cookie&session

第一章 会话技术

1、什么是会话(了解)

在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程,例如,一个用户在某网站上的整个购物过程就是一个会话。

简而言之:从用户访问网站开始到离开网站,关闭浏览器,这个过程就叫会话。

1537159221506.png

注意: 每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。Servlet在会话过程中保存数据使用到的技术有两种:Cookie技术和Session技术。

【小结】

  1. Cookie和Session技术都是在会话期间产生的
  2. Cookie和Session的作用都是保存数据

关于Cookie和Session的相关知识,将在下面的小节进行详细讲解。

第二章 Cookie技术

1、Cookie是什么

Cookie英文意指饼干,Cookie就是服务器暂存放在我们电脑上的一笔资料(where?打开浏览器),使用我们电脑来保存一些服务器希望保存的内容。Cookie是由服务器端生成,发送给浏览器,浏览器会将Cookie以key/value形式的数据保存到某个目录下的文本文件内,下次请求同一网站时就会将该Cookie发送给服务器。当然前提是浏览器设置了启用cookie。

Cookie作用:减轻服务器保存数据的压力。

问题:我们发现将数据保存在浏览器中?而不是保存到服务器或者数据库中?

将数据保存到服务器中,会增加服务器的压力。同时,如果用户不进行购买,并没有带来经济利润。存储到数据库中,如果没有登录到网站,那么将无法查询出数据。而存储到浏览器中可以减轻服务器端压力,并且用户不用登陆也可以将商品添加到购物车中。

关于cookie介绍如下图所示:

cookie概念介绍.png

如何在浏览器中查看当前cookie:

1533001312045.png

1533001358814.png

1533001375815.png

1533001420358.png

注意:通过上面演示我们发现,当我们访问某个网站的时候,网站服务器会在我们浏览器中生成一个cookie,并且存在的时间有的网站还会很久,这样对于用户来说很不好。占用户电脑的硬盘位置。那我们能否禁用cookie,不让网站在我们的电脑浏览器端生产cookie呢?

不可以。因为当我们禁用了cookie,首先商品不能保存到购物车中了,并且由于cookie被禁用了,会导致有的网站我们不能登录了。

2、Cookie的应用场景

在开发中,cookie使用最多的应用场景就是登录页面记住用户名和密码的功能。

1531056973943.png

登录的原理如下图所示:

使用cookie记住用户名和密码案例.png

注意:上述就是使用cookie技术记住用户名和密码的原理。但是由于我们还没有学习如何在页面中获取cookie中的数据,所以今天这里我们暂时还实现不了该整体的功能。但是我们可以使用接下来要学习的cookie的API能够实现除了在页面获取cookie数据的其他功能。

并且可以实现向服务器再次发送请求时,在另一个servlet中从cookie中获取用户名和密码。

实现功能如下图所示:

cookie记住用户名和密码2.png

3、Cookie基本API(重要)

Cookie的基本API包括Cookie的创建,往Cookie中添加数据,获取Cookie中的数据以及将Cookie响应给浏览器。

方法 使用示例 说明
创建Cookie对象 Cookie(String name,String value)name表示指定 cookie 名称 ,value 表示指定 cookie 值 Cookie c1 = new Cookie("username","suoge")
获取cookie的name值 String getName() c1.getName()
获取cookie的value值 String getValue() c1.getValue()
设置cookie的值 void setValue(String value) c1.setValue("李四")

说明:上述都是登录功能中需要的Cookie类中的API.但是该功能除了需要上述API,还需要如下API:

1、HttpServletResponse接口中的方法:
    void addCookie(Cookie cookie)   将cookie发送给浏览器
    
2、HttpServletRequest接口中的方法:
    Cookie[] getCookies()  获取浏览器发送的cookie

4、登录的实现的步骤

  • 步骤一:浏览器发送请求
  • 步骤二:服务器创建cookie并且响应cookie
  • 步骤三:浏览器自动保存cookie
  • 步骤四:浏览器再次发送请求时请求头中会携带cookie (不管第二次请求的是servlet,还是页面)

5、登录案例的代码实现

5.1、登录页面login.html的代码

<form action="/loginServlet" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    记住用户名和密码:<input type="checkbox" name="check"><br>
    <input type="submit" value="提交">
</form>

5.2、登录案例的java后台代码-将cookie响应给浏览器

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决乱码问题
        request.setCharacterEncoding("utf-8");
        //获取用户提交信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");
         /*
            登录业务逻辑处理,到数据库查询用户名和密码是否存在
            假设存在
         */
        //获取CheckBox的值
        String check = request.getParameter("check");
​
        if ("on".equals(check)){
            //用户点击记住用户名和密码
            //生成cookie
            Cookie cookieName = new Cookie("name",username);
            Cookie cookiePwd = new Cookie("pwd",password);
            //将cookie响应回浏览器
            response.addCookie(cookieName);
            response.addCookie(cookiePwd);
        }
    }
}

浏览器接收到服务器响应的cookie结果如下所示:

cookie响应给浏览器结果.png

5.3、登录案例的java后台代码-浏览器再次向服务器发送请求并携带cookie给另一个servlet

【案例】从request请求中获取cookie

第一个案例完成之后,登录成功之后,访问一个新的Servlet,在这个Servlet中获取请求中携带的cookie。

@WebServlet("/getCookieServlet")
public class GetCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //可以获取到浏览器保存所有cookie
        //获取cookie request
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            //获取cookie名称
            if ("name".equals(cookie.getName())){
                System.out.println(cookie.getName());
                //获取cookie的值
                System.out.println(cookie.getValue());
            }else  if ("pwd".equals(cookie.getName()))
            {
                System.out.println(cookie.getName());
                //获取cookie的值
                System.out.println(cookie.getValue());
            }
        }
    }
}

控制台结果

image.png

5.4、关于cookie中存储特殊字符问题 (理解原理即可)

tomcat8之前的版本,不支持中文,tomcat8以后的版本,支持中文.但是如果直接向cookie中存储特殊字符,例如空格,分号(;),逗号(,),等号(=)等特殊字符。那么就会出现问题。在向cookie中存储特殊字符之前必须要先进行编码处理,然后从cookie中取出之后在进行解码处理。

代码演示如下所示:

SpecialServlet.java

@WebServlet("/specialServlet")
public class SpecialServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //向cookie中保存特殊字符
        //定义一个字符串空格
        String str = "12  34";
        //将字符串str存储到cookie中
        Cookie cookie = new Cookie("demo",str);
        //cookie响应回浏览器
        response.addCookie(cookie);
    }
}

浏览器访问服务器结果:

cookie存储特殊字符错误.png

报错原因:cookie中不可以存储特殊的字符。

解决方案:

在向cookie中存储特殊字符之前必须要先进行编码处理,然后从cookie中取出之后在进行解码处理。

编码处理使用的API:

 String encode = URLEncoder.encode(str, "utf-8");

解码处理使用的API:

//对cookie进行解码
String decode = URLDecoder.decode(value, "utf-8");

演示编码处理特殊字符存储到cookie中代码:

@WebServlet("/specialServlet")
public class SpecialServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //向cookie中保存特殊字符
        //定义一个字符串空格
        String str = "12  34";
        //将字符串str存储到cookie中
//        Cookie cookie = new Cookie("demo",str);
​
        //对cookie中保存特殊字符解决方案
        // 对特殊字符进行一次编码
        //进行编码处理
        String encode = URLEncoder.encode(str, "utf-8");
        //将编码之后的数据存储到cookie中
        Cookie cookie = new Cookie("demo",encode);
​
        //cookie响应回浏览器
        response.addCookie(cookie);
    }
}

演示解码处理特殊字符,从cookie中获取数据代码:

@WebServlet("/decodeServlet")
public class DecodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if ("demo".equals(cookie.getName())){
                //获取到当前编码cookie
                String value = cookie.getValue();
                //对cookie进行解码
                String decode = URLDecoder.decode(value, "utf-8");
                //解码后值
                System.out.println("解码后值 = " + decode);
            }
        }
    }
}

注意:上述代码中只要保证编码和解码使用的编码表一致即可。

案例控制台效果图:

image.png

6、Cookie的存活时间&有效路径

在上面的案例中我们发现,将浏览器关闭。然后再打开一个新的浏览器,查看浏览器中的cookie,发现之前保存的cookie都消失了。我们再次登录发现之前设置的Cookie的到期时间为"浏览器会话结束"。

在浏览器设置中查看cookie.png

1530018396006.png

如果,我们想让这个cookie在浏览器关闭后能够在一段时间内都存在,比如记住用户名或密码一周。我们可以通过设置Cookie的最大存活时间来对这个Cookie进行设置。

【Cookie级别】

  • 会话级别 的Cookie:浏览器关闭后消失;
  • 持久化 的Cookie:浏览器关闭后能够保存一段时间;具体的时间可以使用相关API进行设置。

注意:如果没有设置Cookie的保存时间,那么Cookie就是会话级别的Cookie。

6.1 Cookie的最大存活时间(重要)

设置Cookie的最大存活时间的方法是:

方法 使用示例 说明
void setMaxAge(int seconds) userNameCookie.setMaxAge(60*60);设置存活时间是1小时。 设置Cookie的有效时间,单位是秒: 如果没有设置,cookie只会保存在浏览器的缓存中,浏览器关闭后cookie立即被删除。 如果设置有效时间,在时间范围内,cookie被写入到浏览器端,关闭浏览器下次访问仍可活的,直到过期。

【案例1】cookie的存活时间练习

需求:向cookie中存储数据,并设置cookie的存活时间为1周;

@WebServlet("/lifeServlet")
public class LifeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //新建life  cookie
        Cookie cookieLife = new Cookie("life","lifetime");
        //设置cookie存活时间 存活一周
        cookieLife.setMaxAge(60*60*24*7);
        response.addCookie(cookieLife);
    }
}
​

【注意事项】Cookie分类

  1. 会话级别的Cookie:浏览器关闭后销毁;
  2. 持久型的Cookie:设置最大存活时间,在存活的时间内,浏览器关闭,依然存在;

6.2 Cookie的有效路径(了解即可)

当我们访问某个商城网站的时候,由于商城网站会分为多个部分,例如包含用户模块、商品模块等。那么当我们访问用户模块我们希望请求携带的是用户的cookie,而不需要商品的cookie。但是按照我们之前的做法,只要访问服务器,那么所有的cookie都会被携带到服务器中,这并不符合我们开发中的需求。所以我们接下来要学习Cookie的有效路径,只要设置了Cookie的有效路径就可以解决访问哪个模块就携带哪个模块的Cookie。

说明:Cookie的有效路径指的是Cookie允许被访问的路径。设置路径,以及子路径都被允许访问。方法如下:

方法 使用示例 说明
void setPath(String path) cookie.setPath("/suoge") cookie.setPath("/") * cookie.setPath("/suoge"):指的是/suoge路径及其子路径可以访问这个cookie,例如:/suoge/a/b/c都可以访问; *cookie.setPath("/")指的是当前tomcat下的所有的web项目都可以访问这个cookie。如果代码中不进行有效路径的设置,那么就是默认的路径/,即tomcat下的所有的web项目都可以访问这个cookie;

【练习】Cookie的有效路径练习

需求:

  1. 在PathServlet中创建一个Cookie,设置路径为"/suoge/a/b";
  2. 新建一个PathTwoServlet,设置该servlet的访问路径:"/suoge/a/b/d";
  3. 新建一个PathThrServlet,设置该servlet的访问路径:/suoge/a";
  4. 分别在PathTwoServlet,PathThrServlet中获取cookie;

【设置cookie】

1.新建PathServlet,设置有效路径为/suoge/a/b

@WebServlet("/pathServlet")
public class PathServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //给cookie设置有效路径
        Cookie cookie = new Cookie("path","path");
        //给cookie设置生存时间 1小时
        cookie.setMaxAge(60*60);
        //给cookie设置有效路径
        cookie.setPath("/suoge/a/b");
        //cookie响应浏览器
        response.addCookie(cookie);
    }
}

浏览器效果:

image.png

【获取cookie】

新建PathTwoServlet,设置该servlet的访问路径:/suoge/a/b/d

@WebServlet("/suoge/a/b/d")
public class PathTwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println(cookie.getName());
            System.out.println(cookie.getValue());
        }
    }
}

【浏览器效果】

cookie的有效路径2.png

【idea控制台效果】

image.png

注意:浏览器中有什么cookie,那么访问对应的servlet就会在请求中携带什么cookie

新建PathThrServlet,设置该servlet的访问路径:/suoge/a

@WebServlet("/suoge/a")
public class PathThrServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println(cookie.getName());
            System.out.println(cookie.getValue());
        }
    }
}

【浏览器效果】:

cookie有效路径3.png

【idea控制台效果】:

idea的控制台中并没有获取到之前的cookie中的path。

当给cookie设置有效路径"/suoge/a/b"后:

  1. 访问路径:/suoge 获取不到cookie;
  2. 访问路径:/suoge/a/b/d 能获取到cookie ;
  3. 访问路径:/suoge/a/b 能获取到cookie
  4. 访问路径:/suoge/a/d 获取不到cookie;

【结论】

  1. 当设置cookie的有效路径后,只能在有效径或其子路径下访问这个cookie;
  2. 如果不给cookie设置有效路径,默认的有效路径为"/" ,即在当前tomcat下的任意访问路径均可获取这个cookie;

7、Cookie删除(重要)

通常情况下,如果浏览器中的cookie存储的太多,我们要对浏览器中的cookie进行删除。删除浏览器中的cookie有以下几种方式:

1)在浏览器中手动删除cookie;

手动删除cookie.png

2)等待设置cookie的时间到,自动删除;

3)使用代码来删除,Servlet中没有专门提供API去删除cookie。我们可以通过以下方式删除cookie;

说明:思想:置换或者替换。

【操作步骤】

  1. 创建与要删除的cookie同名的cookie,将其值设置成"";
  2. 将这个cookie的最大存活时间设置成0;
  3. 设置这个cookie的有效路径(与原cookie的有效路径一致);
  4. 将这个新的cookie响应给浏览器,置换原来的cookie;

【参考代码】

1.首先生成cookie 代码参考:CreServlet.java

@WebServlet("/creServlet")
public class CreServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建cookie
        Cookie cookie = new Cookie("cre","hello");
        //设置cookie存活时间
        cookie.setMaxAge(60*60);
         //设置路径
        cookie.setPath("/");
        response.addCookie(cookie);
    }
}

效果:

1537160162874.png

cookie删除的操作 参考代码:DeleteServlet.java

@WebServlet("/delServlet")
public class DeleteServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //删除cookie
        //新建相同名称cookie
        Cookie cookie = new Cookie("cre","");
        //保证cookie有效路径一致
        //设置cookie存活时间  0
        cookie.setMaxAge(0);
        //浏览器接受新的cookie,置换之前cookie,完成cookie删除
        response.addCookie(cookie);
    }
}

效果:

关闭浏览器,在浏览器中查看cookie。

找不到cookie.png

【小结】让cookie消失的几种方法

  1. 没有设置最大存活时间的cookie,浏览器关闭后cookie立即消失;
  2. 使用浏览器手动清除cookie;
  3. 浏览器禁用cookie;
  4. 通过Servlet技术将cookie删除;
  5. 等待设置的时间到,自己消失。

8、Cookie小结

  • Cookie:服务器在客户端(浏览器)存储数据的技术;

  • Cookie分类:

    • 会话级别:没有设置最大存活时间的cookie,浏览器关闭后消失;
    • 持久级别:设置了最大存活时间,浏览器关闭后不会消失;
  • Cookie基本API:

    • 创建Cookie:Cookie c = new Cookie("name","zhangsan");
    • 获取name值:c.getName();
    • 获取value值:c.getValue();
    • 将cookie响应给浏览器:response.add(c);
    • 获取所有的cookie:Cookie[] cookies = request.getCookies();
  • Cookie的有效时间:

    • setMaxAge(int seconds):以秒为单位设置cookie的存活时间;
  • Cookie的有效路径:

    • setPath(String path):设置cookie的有效路径,在这个路径及其子路径下有效;
  • Cookie删除:

    • 客户端:

      • 会话级别的cookie,关闭浏览器后cookie立即消失;
      • 禁用cookie;
      • 手动清除cookie;
    • 服务端:

      • 通过Servlet,将原来的cookie置换;
  • Cookie的优势及弊端:

    • 优势:

      • 为服务端标识用户提供依据;
      • 减轻了服务端数据存储的压力;
    • 弊端:

      • 数据存储在客户端不安全;
      • 存储的数据大小受限,一个cookie存储的数据最大为4K;

猜你喜欢

转载自juejin.im/post/7240465997002195003