Web开发之Cookie

会话跟踪技术

会话可以简单的理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应。例如,用户在某个浏览器中访问某一个 Web 应用,只要不关闭该浏览器,不管该用户点击该 Web 应用的多少个超链接,访问多少资源,直到关闭浏览器之前,整个的这个访问过程我们称为一次会话

在一个会话的多个请求中共享数据,这就是会话跟踪技术。会话跟踪技术可以解决我们很多问题。比如最常见的就是一个用户在登陆一个网站之后,请求该网站的其他页面和资源时免登录的功能,又比如购物网站中常见的显示曾经浏览过的商品的功能,又比如某些购物网站允许未登录用户可以添加商品到临时购物车中的功能

常见的会话跟踪技术有 CookieSessionCookie 是先出现的

Cookie 概述

由于 HTTP 是一种无状态的协议,但为了实现期望的保持状态功能,于是引入了 Cookie 技术。Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态

简单的说:Cookie 是由服务器创建,然后通过响应发送给客户端的一个键值对,这个键值对中包含了要该会话想要记住的状态信息,客户端会保存这个 Cookie,并会标注出 Cookie 的来源(哪个网站的 Cookie)。当客户端再一次向该网站发出请求时会把所有这个网站的 Cookie 包含在请求报文头中发送给服务器,这样服务器就可以根据该请求携带的 Cookie 信息识别客户端,并且得到之前的状态信息了

第一次,没有 Cookie 信息状态下的请求

在这里插入图片描述
第二次开始,存有 Cookie 信息状态的请求

在这里插入图片描述

Cookie 的简单使用

JavaServlet 规范中,可以非常简单的设置和获取 CookieCookie 被抽象成为一个 Cookie

  • 当要设置 Cookie 的时候,需要创建 Cookie 对象并且设置 keyvalue,随后通过 response 响应对象的 addCookie() 方法添加这个 Cookie 即可,Web 服务器会自动将 response 中的 Cookie 发送给客户端
  • 客户端在随后对该 Web 应用的其他资源进行访问的时候,将会自动带上服务器发送的 Cookie(同一个服务器的其他 Web 应用也不会发送)
@WebServlet("/cookie-servlet")
public class CookieServlet extends HttpServlet {
    
    

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset=utf-8");
        // 生成一个随机字符串
        String id = UUID.randomUUID().toString();
        // 创建Cookie对象,指定名字和值。Cookie类只有这一个构造器
        Cookie cookie = new Cookie("id", id);
        // 在响应中添加Cookie对象
        resp.addCookie(cookie);
        resp.getWriter().print("已经给你发送了ID");
    }
}

在访问 /hello-servlet 资源时,用于测试 Cookie,该 Servlet 中通过 request 请求对象的 getCookies() 方法获取 Cookie

@WebServlet("/hello-servlet")
public class HelloServlet extends HttpServlet {
    
    

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    
    
        Cookie[] cookies = request.getCookies();
        // 如果请求中存在Cookie
        if (cookies != null) {
    
    
            // 遍历所有Cookie
            for (Cookie c : cookies) {
    
    
                // 获取Cookie名字,如果Cookie名字是id
                if ("id".equals(c.getName())) {
    
    
                    response.getWriter().print("您的ID是:" + c.getValue());
                }
            }
        }
    }
}

Cookie 细节

Cookie 的覆盖

如果服务器端多次发送重复 keyCookie,那么后发送的 Cookie 会覆盖原有的 Cookie,例如客户端的第一个请求服务器端发送的 Cookie 是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个 Cookie,即:a=AA

如果服务器端一次发送多个重复 keycookie,那么当客户端再次请求的时候,只携带最后一个设置的 Cookie 的值

Cookie 有效期

所谓 Cookie 的有效期就是 Cookie 在客户端的最大有效时间,我们可以通过 setMaxAge(int) 方法来设置 Cookie 的有效时间,单位秒

  • cookie.setMaxAge(-1)cookiemaxAge 属性的默认值是 -1,表示只在浏览器内存中存活。一旦关闭浏览器窗口,那么 cookie 就会消失。生命值为负数的 Cookie 也被称为内存 Cookie
  • cookie.setMaxAge(60*60):表示 cookie 对象可存活 1 小时。当生命值大于 0 时,浏览器会把 Cookie 保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie 也会存活 1 小时,除非将 Cookie 从硬盘上手动清理了。生命值为正数的 Cookie 也被称为硬盘 Cookie
  • cookie.setMaxAge(0)cookie 生命值等于 0 是一个特殊的值,它表示 cookie 被作废。也就是说,如果原来浏览器已经保存了这个 Cookie,那么可以通过 CookiesetMaxAge(0) 来要求浏览器删除这个 Cookie。无论是在浏览器内存中,还是在客户端硬盘上都会删除这个 Cookie

Cookie 修改和删除

Cookie 并没有提供直接的修改和删除功能,但是根据前面 Cookie 的覆盖和有效期属性,可以间接的修改和删除 Cookie

当想要修改 Cookie 时,可以发送同名 keyCookie,这样以前的旧 Cookie 就被覆盖了。当想要删除 Cookie 时,同样设置同名 keyCookiemaxAge = 0 即可

Cookie 与跨域问题

默认情况下,不同的域名中设置的 Cookie 不可以共享,即跨域问题

cookie 有一个 setDomain() 方法,可以设置 Cookiedomain 属性(域名),表示 Cookie 在域名级别中的作用范围。如果不设置,那么默认范围就是当前域名

猜你喜欢

转载自blog.csdn.net/weixin_38192427/article/details/115032879