cookie和session

什么是Cookie?

HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器发起请求时被携带并发送到服务器上。通常,它被用于服务端判断两个请求是否来自于同一浏览器。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。

Cookie 主要用于以下三个方面:

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)

  • 个性化设置(如用户自定义设置、主题等)

  • 浏览器行为跟踪(如跟踪分析用户行为等)

Cookie的流程:浏览器访问服务器,如果服务器需要记录该用户的状态,就使用response向浏览器发送一个Cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的网址连同Cookie一同交给服务器。

Cookie API

  • Cookie类用于创建一个Cookie对象
  • response接口中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段
  • request接口中定义了一个getCookies方法,它用于获取客户端提交的Cookie

常用的Cookie方法:

  • public Cookie(String name,String value)
  • setValue与getValue方法
  • setMaxAge与getMaxAge方法
  • setPath与getPath方法
  • setDomain与getDomain方法
  • getName方法

简单使用Cookie

  • 创建Cookie对象,发送Cookie给浏览器
        //设置response的编码
        response.setContentType("text/html;charset=UTF-8");
        //创建Cookie对象,指定名称和值
        Cookie cookie = new Cookie("username", "zhongfucheng");        
        //向浏览器给一个Cookie
        response.addCookie(cookie);
        response.getWriter().write("我已经向浏览器发送了一个Cookie");
删除cookie
        String name = "看完博客就点赞";
        //对Unicode字符进行编码
        Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
        //一定不要忘记添加到浏览器中
        cookie.setMaxAge(0);
        response.addCookie(cookie);
        printWriter.write("我删除了该Cookie");
  • 注意:删除,修改Cookie时,新建的Cookie除了value、maxAge之外的所有属性都要与原Cookie相同。否则浏览器将视为不同的Cookie,不予覆盖,导致删除修改失败

什么是Session?

Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话,或者 Session 超时失效时会话结束。如果说Cookie是检查用户身上的”通行证“来确认用户的身份,那么Session就是通过检查服务器上的”客户明细表“来确认用户的身份的。Session相当于在服务器中建立了一份“客户明细表”。

Session比Cookie使用方便,Session可以解决Cookie解决不了的事情【Session可以存储对象,Cookie只能存储字符串。】。

Session API

  • long getCreationTime();【获取Session被创建时间】
  • String getId();【获取Session的id】
  • long getLastAccessedTime();【返回Session最后活跃的时间】
  • ServletContext getServletContext();【获取ServletContext对象】
  • void setMaxInactiveInterval(int var1);【设置Session超时时间】
  • int getMaxInactiveInterval();【获取Session超时时间】
  • Object getAttribute(String var1);【获取Session属性】
  • Enumeration getAttributeNames();【获取Session所有的属性名】
  • void setAttribute(String var1, Object var2);【设置Session属性】
  • void removeAttribute(String var1);【移除Session属性】
  • void invalidate();【销毁该Session】
  • boolean isNew();【该Session是否为新的】

Session的生命周期和有效期

  • Session在用户第一次访问服务器Servlet,jsp等动态资源就会被自动创建,Session对象保存在内存里,这也就为什么上面的例子可以直接使用request对象获取得到Session对象
  • 如果访问HTML,IMAGE等静态资源Session不会被创建。
  • Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,无论是否对Session进行读写,服务器都会认为Session活跃了一次
  • 由于会有越来越多的用户访问服务器,因此Session也会越来越多。为了防止内存溢出,服务器会把长时间没有活跃的Session从内存中删除,这个时间也就是Session的超时时间
  • Session的超时时间默认是30分钟,有三种方式可以对Session的超时时间进行修改

  • 第一种方式:在tomcat/conf/web.xml文件中设置,时间值为20分钟,所有的WEB应用都有效

            <session-config>
                <session-timeout>20</session-timeout>
            </session-config>   
  • 第二种方式:在单个的web.xml文件中设置,对单个web应用有效,如果有冲突,以自己的web应用为准
            <session-config>
                <session-timeout>20</session-timeout>
            </session-config>   
  • 第三种方式:通过setMaxInactiveInterval()方法设置
        //设置Session最长超时时间为60秒,这里的单位是秒
        httpSession.setMaxInactiveInterval(60);

        System.out.println(httpSession.getMaxInactiveInterval());

为什么需要 Cookie 和 Session,他们有什么关联?

说起来为什么需要 Cookie ,这就需要从浏览器开始说起:浏览器是没有状态的(HTTP 协议无状态),这意味着浏览器并不知道是张三还是李四在和服务端打交道,这个时候就需要有一个机制来告诉服务端,本次操作用户是否登录,是哪个用户在执行,这套机制的实现就需要 Cookie 和 Session 的配合。

用户第一次请求服务器时,服务器根据用户提交的相关信息,创建对应的 Session ,请求返回时将此 Session 的唯一标识信息 SessionId返回给浏览器,浏览器接收到服务器返回的 SessionId信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionId属于哪个域名。当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionId,再根据 SessionId查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。

根据以上流程可知,SessionId是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

浏览器禁止了Cookie,怎么办?

第一种方案,每次请求中都携带一个 SessionId的参数,也可以 Post 的方式提交,也可以在请求的地址后面拼接 xxx?SessionId=1111···

第二种方案,Token 机制。Token 机制多用于 App 客户端和服务器交互的模式,也可以用于 Web 端做用户状态管理。

Token与Session的区别?

Session机制:用户信息存储在服务器端,可能出现用户过多造成服务器端太大压力;

Token机制:Token在服务器时可以不用存储用户信息的,Token传递的方式也不局限于Cookie传递,Token也可以保存起来。浏览器第一次访问服务器时,会传过来一个唯一表示ID,服务端通过算法,加密钥,生成一个Token。通过BASE64编码后将Token发送给客户端。客户端将Token保存起来,下次请求带着Token,服务器收到请求会用相同的算法取验证Token,如果通过就继续执行。
Token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由Token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接Token请求服务器)。还可以把不变的参数也放进Token,避免多次查库。类似于每个人都有的身份证,用户信息存在于客户端,有客户端存储,服务端只需要验证Token是否合法。

分布式 Session 问题?

在互联网公司为了可以支撑更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在 A 服务器登录了,第二次请求跑到服务 B 就会出现登录失效问题。

分布式 Session 一般会有以下几种解决方案:

  • Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。

  • Session 复制,任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。

  • 共享 Session,服务端无状态话,将用户的 Session 等信息使用缓存中间件(例如redis)来统一管理,保障分发到每一个服务器的响应结果都一致。

建议采用第三种方案。

原文地址:https://www.cnblogs.com/caozx/p/10867727.html