客户端会话技术Cookie


概述

Cookie - - 也称Cookies,是客户端技术,指网站为了辨别用户身份、进行session跟踪而存储在用户本地终端上的数据(一般都是经过加密的),Cookie也称为浏览器缓存。服务器把每个用户的数据以cookie的形式写给用户各自的浏览器,当客户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。
在这里插入图片描述
什么是会话?
用户打开一个浏览器点击多个超链接,访问服务器多个web资源(包含多次请求和响应),到最后关闭浏览器,整个过程称为一个会话。

会话技术解决什么问题?
保存各个客户端自己的数据,每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自产生一些数据,会话技术就是用来为每个用户保存这些数据,即在一次会话的多次请求之间共享数据

生活中遇到的会话技术?
由于http协议是无状态的协议,每次都是基于一个请求和一个响应,每次请求和响应都和上一次没有关系。比如当我们访问web应用时,服务器无法区分该客户端是谁,如在网上购买东西,当我们添加商品到购物车,每一次添加一个商品,就会有对应的一个响应,但是当我们添加多个商品到购物车,很明显每添加一次商品的请求和响应和上一次添加商品的请求与响应都没有关系,所以服务器必须根据请求我们的身份,找到我们所添加到购物车的所有商品,针对我们这个用户,这时候用到就是会话技术。

以下是打开我的浏览器查看的cookie数据,虽然说明本地能存在少量不太敏感的信息,但是不安全
在这里插入图片描述

Cookie原理

cookie实现发送和接收过程 :客户端发送请求给服务器 -> 服务器发送响应头set-cookie并携带数据给客户端 -> 客户端将响应头携带的数据保存到客户端浏览器中 -> 下一次请求时客户端会使用消息头cookie数据携带给服务器 -> 服务器获取消息头中的数据

当用户第一次发出请求后,由服务器创建cookie对象,通过response对象响应给客户端浏览器数据
当用户第二次发出请求后,会携带上一次由服务器创建并响应过来的这个cookie给服务器

cookie底层是由Http协议实现的,通过头来进行创建(Set-Cookie),创建后通过response对象的addHeader(“Set-Cookie”,“name=monkey”)的方法写回给客户端,而客户端可以通过request.getHeader(“Cookie”)或者request.getCookies();来获取该服务器所有的cookie

其实就是基于响应头Set-Cookie和请求头Cookie 实现的
在这里插入图片描述

Cookie的使用

①创建Cookie对象Cookie cookie = new Cookie(String name,String value);
name - - 当前Cookie的唯一名字
value - - 存储在Cookie的共享数据

Cookie cookie  = new Cookie("MyName","monkey");

②服务器向客户端发送Cookie对象,把共享数据存储到浏览器中response.addCookie(cookie);
③客户端获取Cookie以及里面的数据Cookie[] cs = request.getCookies();

@WebServlet("/CookieDemo1")
public class CookieDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.创建 Cookie对象,绑定数据
        Cookie c1 = new Cookie("MyName","monkey");
        Cookie c2 = new Cookie("OtherName","dog");
        //2.服务器发送Cookie对象给浏览器客户端
        response.addCookie(c1);
        response.addCookie(c2);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

@WebServlet("/CookieDemo2")
public class CookieDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //浏览器接收Cookie以及其数据
        Cookie[] cs = request.getCookies();
        if(cs != null){
            for(Cookie c : cs){
                String name = c.getName();
                String value = c.getValue();
                System.out.println(name+":"+value);
            }
        }
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           this.doPost(request, response);
    }
}
  • 一次课创建多个cookie对象,使用response调用多次addCookie方法发送cookie给客户端
  • 这里注意一个问题,tomcat启动,如果我打开谷歌浏览器访问CookieDemo1,此时服务器发送了cookie给客户端,在同一个浏览器访问CookieDemo2来接收cookie是可以的,去另一个浏览器访问CookieDemo2是行得通的,说明cookie可以被多个浏览器共享。

关于cookie是否可以存储中文

当我按照上面写的代码在cookie中存入中文时,启动tomcat访问CookieDemo1后,报错,必须对中文的内容进行转码解码(网上有说tomcat8版本之后支持中文,我寻思着我也是8啊→_→)
在这里插入图片描述
当cookie存放中文时,出现乱码情况时,或者以上情况500报错,需要URL编解码,即存放时编码,接收时解码

//存放
String value = Encoder.encode("小猴","utf-8");
Cookie cookie = new Cookie("MyName",value);
//接收
String value = Decoder.decode(cookie.getValue(),"utf-8");

以下是对中文内容的转码和解码来发送和接收cookie

@WebServlet("/CookieDemo1")
public class CookieDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //测试设置同名Cookie
        
        /*这是对中文内容的转码方式一
        String val1 = java.net.URLEncoder.encode("我","utf-8");
        Cookie c1 = new Cookie("MyName",val1);
        */
        
        //这是对中文内容的转码方式二
        Cookie c1 = new Cookie("MyName", URLEncoder.encode("我是谁","utf-8"));
        c1.setMaxAge(20); //设置cookie的生命周期,20s
        response.addCookie(c1);
        
       /*
        String val2 = java.net.URLEncoder.encode("你","utf-8");
        Cookie c2 = new Cookie("MyName",val2);
        */
        Cookie c1 = new Cookie("MyName", URLEncoder.encode("你","utf-8"));
        c2.setMaxAge(20); //设置cookie生命周期,20s,20s后消失
        response.addCookie(c2);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
@WebServlet("/CookieDemo2")
public class CookieDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //浏览器接收Cookie以及其数据
        Cookie[] cs = request.getCookies();
        if(cs != null){
            for(Cookie c : cs){
                String name = c.getName();
                String value = java.net.URLDecoder.decode(c.getValue(),"utf-8");
                System.out.println(name+":"+value);
            }
        }
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           this.doPost(request, response);
    }
}
  • 运行结果 我是谁的中文字样没有出现,只有 你 的中文出现,说明设置了Cookie的name值相同时,后一个会覆盖前一个的设置。
  • 以上代码在我运行CookieDemo2时,20s运行控制台会出现你的中文字样,20s后就不会再出现,说明在设置的20s存活时间之后,即使我没关闭浏览器,cookie也被销毁了
  • Cookie在浏览器中保存时间
    ①默认情况下,浏览器关闭后,Cookie数据被销毁
    ②持久化存储:
setMaxAge(int seconds) //可以设置多少s来规定cookie的存活时间
参数:
正数 - - 将Cookie数据写到硬盘文件中,持久化存储,同时参数代表文件存在时间,时间一过就销毁
0 - - 删除Cookie信息
负数 - - 默认值,浏览器一关就销毁

Cookie小结

1.Cookie是在服务器创建的,保存于浏览器缓存文件中,同时cookie的生命周期是可设置的cookie.getMaxAge(time);//以秒为单位,不设置时,关闭浏览器默认Cookie销毁。
2.Cookie存储数据在客户端浏览器,一般用于存储少量的不太敏感的数据
3.共享数据时保存在浏览器中,容易造成数据的泄漏,不安全。解决方案:将数据保存在服务端(session)
4.一个web应用可以保存多个Cookie,并且会保存在浏览器缓存文件夹的同一个文件夹
5.浏览器对于单个Cookie的大小有限制,cookie在浏览器中也有数量的限制(4kb),一个浏览器站点最多存储20个Cookie信息,一个浏览器最多只能存储300个Cookie
6.关于Cookie的路径:

在同一个tomcat服务器中,部署了多个web项目,在这些web项目中Cookie能否共享

  • 默认情况下。cookie不能共享,默认情况下cookie获取范围设置为当前项目的虚拟目录setPath(String path)
  • 如果想要多个项目之间可以共享,可将path设置为/ 即setPath("/")

在不同的tomcat服务器之间共享

  • 若设置一级域名相同,则多个服务器之间cookie可以共享 setDomain(String path)
package monkey.study.web.cookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

@WebServlet("/CookieDemo3")
public class CookieDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String value = URLEncoder.encode("小猴","utf-8");
        Cookie c1 = new Cookie("MySelf",value);
        c1.setPath("/");//设置path,当前tomcat服务器下部署的所有项目共享Cookie
        response.addCookie(c1);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
package monkey.study.web.cookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/CookieDemo2")
public class CookieDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //浏览器接收Cookie以及其数据
        Cookie[] cs = request.getCookies();
        if(cs != null){
            for(Cookie c : cs){
                String name = c.getName();
                String value = java.net.URLDecoder.decode(c.getValue(),"utf-8");
                System.out.println(name+":"+value);
            }
        }
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           this.doPost(request, response);
    }
}

案例

1.保存上次登录时间:访问一个Servlet,第一次访问则提示:这是你第一次登录;若是第二次访问则提示欢迎回来,上次访问时间是:‘显示上次访问时间’
在这里插入图片描述

package monkey.study.web.cookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;

@WebServlet("/CookieDemo1")
public class CookieDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8"); //设置响应体数据格式以及编码
        Cookie[] cookies = request.getCookies(); //客户端浏览器获取cookie以及里面的数据
        boolean flag =false;//没有LastTime的cookie
        if (cookies != null && cookies.length > 0){
            //遍历循环cookie,查找是否有存在LastTime的cookie,Cookie名为LastTime存储了上一次访问时间
            for (Cookie cookie : cookies){
                String name = cookie.getName();
                if ("LastTime".equals(name)){  //不是第一次访问
                    String value = cookie.getValue();
                    response.getWriter().write("欢迎回来,上次访问时间:"+value);
                   //response.getWriter().write("欢迎回来,上次访问时间:"+value);
                   updateDate(response); //更新时间,将此次时间存储到cookie
                   flag = true; //有LastTime的cookie,标记为不是第一次访问
                }
            }
        }
        if (!flag){  //第一次访问
            updateDate(response);//更新时间,将这一次的时间存储到cookie
            response.getWriter().write("这是你第一次访问");
        }
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
    private void updateDate(HttpServletResponse response) throws UnsupportedEncodingException {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String now_date = simpleDateFormat.format(date);
        Cookie cookie = new Cookie("LastTime",now_date);
        cookie.setValue(now_date); //更新LastTime存储的时间
        cookie.setMaxAge(3600*24*7);//七天有效期
        response.addCookie(cookie); //服务器向客户端浏览器发送cookie
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值