Cookie和Session

简介

存储客户端的状态

由一个问题引出今天的内容,例如网站的购物系统,用户将购买的商品信息存储到哪 里?因为Http协议是无状态的,也就是说每个客户访问服务器端资源时,服务器并 不知道该客户端是谁,所以需要会话技术识别客户端的状态。会话技术是帮助服务器 记住客户端状态(区分客户端)

把数据保存在request中,多次请求不能保存数据
把数据保存在servletContext中,所有用户共用一个域,容易出现冲突

会话技术

从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话。会 话技术就是记录这次会话中客户端的状态与数据的。
会话技术分为Cookie和Session:
Cookie:数据存储在客户端本地,有大小限制,减少服务器端的存储的压力,安全性不好,客户端 可以清除cookie
Session:将数据存储到服务器端,安全性相对好,增加服务器的压力

这里写图片描述

这里写图片描述

这里写图片描述

Session对象的生命周期(面试题/笔试题)

创建:第一次执行request.getSession()时创建
销毁:
1)服务器(非正常)关闭时
2)session过期/失效(默认30分钟)

问题:时间的起算点 从何时开始计算30分钟?
从不操作服务器端的资源开始计时

可以在工程的web.xml中进行配置

<session-config>
        <session-timeout>30</session-timeout>
</session-config>

3)手动销毁session
session.invalidate();
不过这个方法在实际的开发中,并不推荐,可能在强制注销用户的时候会使用;

作用范围:
默认在一次会话中,也就是说在,一次会话中任何资源公用一个session对象

面试题:浏览器关闭,session就销毁了?
 不对,销毁的是cookie而不是session,浏览器可以设置保存cookie

我们知道Session是存在于服务器端的,当把浏览器关闭时,浏览器并没有向服务器发送任何请求来关闭Session,自然Session也不会被销毁,但是可以做一点努力,在所有的客户端页面里使用js的window.onclose来监视浏览器的关闭动作,然后向服务器发送一个请求来关闭Session,但是这种做法在实际的开发中也是不推荐使用的,最正常的办法就是不去管它,让它等到默认的时间后,自动销毁。那么为什么当我们关闭浏览器后,就再也访问不到之前的session了呢?其实之前的Session一直都在服务器端,而当我们关闭浏览器时,此时的Cookie是存在于浏览器的进程中的,当浏览器关闭时,Cookie也就不存在了。
其实Cookie有两种:
一种是存在于浏览器的进程中;
一种是存在于硬盘上。
而session的Cookie是存在于浏览器的进程中,那么这种Cookie我们称为会话Cookie,当我们重新打开浏览器窗口时,之前的Cookie中存放的Sessionid已经不存在了,此时服务器从tpServletRequest对象中没有检查到sessionid,服务器会再发送一个新的存有Sessionid的Cookie到客户端的浏览器中,此时对应的是一个新的会话,而服务器上原先的session等到它的默认时间到之后,便会自动销毁。

杂谈

/**
 * Cookie是客户端技术,程序把用户的数据以cookie的形式返回给浏览器,之后用户访问web就会带着cookie去
 * 这样web处理的就是用户自己的数据
 * 
 * session是服务器端技术,服务器为每个用户浏览器创建一个HttpSession对象,
 * 当用户访问web的其他资源的时候,web从Session中取出数据,--------一个浏览器对应一个偶---------
 * 
 * HttpServletRequest.getCookie   HttpServletResponse.addCookie
 * 
 * cookie的存储时间可以自定义 ck.setMaxAge(60*5);  保存五分钟
 * 
 * 开两个火狐浏览器,能不能取到相同的cookie取决于cookie是否存放到磁盘中,两个会话有各自的缓存信息
 *      
 */
@WebServlet("/show0")
public class show0 extends HttpServlet {
    //-------------------------记录上次登录时间------------------------------
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取客户端保存的最后访问时间,先判断有没有cookie,第一次是没有的

            response.setContentType("text/html;charset=UTF-8");

            PrintWriter out =response.getWriter();
            Cookie[] cookies=request.getCookies();  //获取客户端的所以cookie
            for(int i=0;cookies!=null && i<cookies.length;i++){
                if("lastAccessTime".equals(cookies[i].getName())){
                    long l=Long.parseLong(cookies[i].getValue());
                    out.write("你最后访问的时间:"+new Date(l).toLocaleString());
                }
            }


        //创建cookie,把信息返回客户端
            Cookie ck=new Cookie("lastAccessTime", System.currentTimeMillis()+"");
            response.addCookie(ck);

    }


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        doGet(request, response);
    }

}
  服务端存储会话ID有多种方式,常见的有本地存储,如:普通文本,文本名就是会话ID。
  对于文件系统,同一目录下,同一文件名只允许唯一一个文件,那么使用会话ID作为文件名是可以做到唯一确定会话的。
  除了本地文件存储,还可以使用memcache、redis、或者Mysql之类的数据库存储,即使用第三方数据库进行存储。
  只有一个原则:存储的会话ID必须是唯一的。

     客户端收到服务端返回的(或者说服务端下发的)会话ID后,也是像服务端那样使用文件名作为会话ID存储会话信息到文本吗?
     如果客户端只与同一个服务端(理解为同一个服务端处理程序)进行会话通讯的话,是可行的。但是,HTTP是因万维网而生的,
     浏览器作为最常见的HTTP客户端,需要访问各种不同的网站,如果采用会话ID作为文件名,以这样的文件存在会话信息的话,
     会出现这样的情况:N个不同的网站,服务端采用的是相同的会话生成算法,在同一时刻,很可能会生成一样的会话ID,
     客户端则无法唯一确定这个会话ID到底是与哪个服务端通讯,也就是客户端“不认得”服务端了,会话就无法完成。如何确定服务端身份?
     那就是使用“域”,不同的域拥有独立的会话。客户端以域相关信息作为文件标识符创建会话文件(客户端存储)对会话信息进行存储,
     其中域与会话ID结合就能唯一确定服务端,并且确定会话。那么,以“域”信息作为文件名的文件中存储着会话ID等信息。
     每次请求某个域的服务时,把存储着的会话ID附带到请求中发送到服务端。浏览器是最常见的HTTP客户端,浏览器存储会话信息,
     是使用COOKIE文件的,里面保存着COOKIE信息,而服务端返回的会话ID也存储在里面。会话ID存储在COOKIE文件中是一般情况下的,
     而COOKIE信息是作为HTTP头发送给服务端的,也就是说这种情况下,会话ID是附带在请求头中。但是,HTTP请求,除了头信息,
     还可以有内容体,必须有URL。那么,会话ID同样可以存储在内容体中或URL中,比如在禁用浏览器COOKIE的情况下,
     也可实现与服务端会话,要么依赖内容体,要么依赖URL,常见的是URL中附带会话ID,
     这个在PHP等编程语言中较为常见(曾经的历史上常见,但是会涉及安全或者效率等问题,这里不详述)。

    粗糙地,可理解为服务端返回给客户端的会话ID是存储在COOKIE文件中的。COOKIE文件是由浏览器管理的,
当然在自实现的客户端中,可以通过编程手段实现COOKIE文件管理,即客户端会话的管理。举例:IOS开发者,
    可以把HTTP返回的信息头存储到沙盒中进行管理。PHP开发客户端时,可以把信息头写到文件中,或第三方服务中,或网络存储中等等。

客户端禁用Cookie后的会话数据保存问题
客户端禁用cookie:浏览器永远不会向服务器发送cookie的请求消息头

解决方案:
方案一:在主页上给出提示:请不要禁用您的cookie
方案二:URL重写。必须对网站的所有地址都重写。

http://url—>http://url;JSESSIONID=111

response.encodeURL(String url);
看浏览器有没有发送cookie请求消息头,没有就重写URL,有就不重写。

request.getSession();必须写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值