热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:Session与Cookie

1.会话技术简介http协议是无状态的,因此对于服务端来说,当它接收到客户端的http请求时,无法识别这个请求来源于哪个客户端。无状态的协议有优点也有缺点,

1.会话技术简介

  http协议是无状态的,因此对于服务端来说,当它接收到客户端的http请求时,无法识别这个请求来源于哪个客户端。无状态的协议有优点也有缺点,但对于需要识别客户端甚至是需要记住客户端的业务来说,应当要让http协议"有状态"。

  需要记住客户端的业务种类非常多。例如登陆系统,在一个页面登录后,新打开一个该网站页面,应当也保持登录状态。再例如购物车系统,某用户添加商品1后应当保证他还能继续添加商品2,在结算时能够读取购物车中的所有商品。

  如何让服务端记住客户端?目前使用最多的是COOKIE和session两种会话技术。


  • 1.COOKIE:数据存储在客户端本地,减少服务器端的存储的压力,安全性不好,客户端可以清除COOKIE。

  • 2.Session:将数据存储到服务器端,安全性相对好,会增加服务器的压力。


  COOKIE技术是将用户的数据存储到客户端的技术,它的作用是为了让服务端根据每个客户端持有的COOKIE来区分不同客户端。

  COOKIE由COOKIE name、具有唯一性的COOKIE value以及一些属性(path、expires、domain等)构成,其中value是区分客户端的唯一依据。

  COOKIE的原理为:服务端在接收到客户端首次发送的请求后,服务端在响应首部中加入"set-COOKIE"字段发送给客户端;客户端接收响应后,将COOKIE信息存储到内存中(如果设置了MaxAge属性,则存储到磁盘中);因为COOKIE数据在浏览器的内存中,因此无论是哪个页面,客户端再次向服务端发送请求时都能获取该COOKIE信息,并在请求首部中加入"COOKIE"字段发送给服务端;服务端借此就可以识别客户端,并从COOKIE中找到该客户端的信息。

技术图片

使用COOKIE需要解决的两个问题:


  • (1).服务端怎样将一个COOKIE发送到客户端。

  • (2).服务端怎样接受客户端携带的COOKIE。


设置COOKIE涉及的几个常用方法为:


  • COOKIE(String COOKIE_name,String COOKIE_value):构造一个COOKIE对象。

  • setPath(uri):当访问属于该uri下的路径(包括子路径)时,该COOKIE都生效,例如setPath("/COOKIE"),当本机使用http://localhost/COOKIE/servlet1http://localhost/COOKIE/servlet2访问时,都拥有该COOKIE。

  • setMaxAge(int second):设置该属性时,COOKIE将持久化保存到客户端的磁盘中,保存时间为second秒。如果COOKIE不具有该属性,则COOKIE只会存放在内存中。

  • setDomain(String domain):设置COOKIE生效的域范围,例如COOKIE.setDomain(".foo.com");,这将对foo.com域下的所有主机都生效(如www.foo.com),但不包括子域(www.abc.foo.com)。

  设置好COOKIE后,需要使用response的方法addCOOKIE(COOKIE COOKIE)将COOKIE加入到响应首部中发送给客户端。

  例如,以下是名为CooikeDemo工程的一个servlet,该servlet的uri路径为"/COOKIEservlet"。

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.COOKIE;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class COOKIEServlet extends HttpServlet {
private static final long serialVersiOnUID= 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
COOKIE COOKIE
= new COOKIE("username","zhangsan"); //构造COOKIE对象
COOKIE.setPath("/COOKIEDemo"); //设置COOKIE生效的uri范围
COOKIE.setMaxAge(10*60); //设置COOKIE持久到磁盘的时间为10分钟
response.addCOOKIE(COOKIE); //在响应首部中加入set-COOKIE字段并发送给客户端
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

 

该COOKIE将会在响应首部加入set-COOKIE字段发送给客户端:
技术图片

当客户端再次请求时,将在请求首部中加入COOKIE字段。
技术图片

需要注意的几点:


  • (1).COOKIE中不能存储中文。

  • (2).如果不设置持久化时间,COOKIE会存储在浏览器的内存中,浏览器关闭时COOKIE信息销毁,这是会话级的COOKIE。如果设置持久化时间,COOKIE信息会被持久化到磁盘中,这是持久级别的COOKIE。持久化后的COOKIE不会随浏览器关闭而失效,而是在有效时间内都有效。

  • (3).setPath()设置的生效路径为目录时,则COOKIE对该目录和子目录下的资源都生效,如果生效路径为文件时,则只对该文件有效。例如:


    COOKIE.setPath("/webapp"); //代表访问webapp应用中的任何资源都携带COOKIE
    COOKIE.setPath("/webapp/COOKIEservlet"); //代表访问webapp中的COOKIEservlet时才携带COOKIE信息

     


  • (4).如果想要删除当前还有效的COOKIE信息,可以使用同名同路径的持久化时间为0的COOKIE进行覆盖。这样一来,每次客户端接收到响应后COOKIE就立即失效,也就无法携带COOKIE请求服务端。例如删除上面示例的COOKIE信息

    COOKIE COOKIE = new COOKIE("username","zhangsan");
    COOKIE.setPath(
    "/COOKIEDemo");
    COOKIE.setMaxAge(
    0);
    response.addCOOKIE(COOKIE);

     



  如前面的图中所示,客户端的COOKIE信息是以请求头的方式发送到服务器端的。因此服务端要获取COOKIE信息,需要使用request对象中的方法getCOOKIEs()。这时唯一的获取COOKIE的方法,它返回的是COOKIE数组集合,因此需要遍历该数组才能获取指定名称的COOKIE。

  例如,获取COOKIE name为"username"的COOKIE。

COOKIE[] COOKIEs = request.getCOOKIEs();
if(COOKIEs != null) {
for (COOKIE coo : COOKIEs) {
String COOKIE_name
= coo.getName();
if (COOKIE_name.equals("username")) {
String COOKIE_value
= coo.getValue();
System.out.println(COOKIE_name
+":"+COOKIE_value);
}
}
}

 

3.Session技术

  从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程(释放浏览器内存),成为一次会话。除了COOKIE技术可以让服务端在一次会话过程中记住客户端,Session技术也可以达到这样的目的。

  Session技术将数据存储在服务器端,它会为每个客户端都创建一块内存空间存储客户端数据,并为客户端分配一个存储在COOKIE中的JSESSIONID,客户端需要每次都携带一个这个ID,服务器通过这个ID可以找到属于该客户端的内存空间。由于这个标识ID是借助COOKIE存储的唯一性标识JSESSIONID,因此Session是基于COOKIE来实现的。

技术图片

  Session的原理:服务端接收到某客户端首次发送的请求后,为此客户端生成一个session,并分配一段属于该session的缓冲区,同时将该session配对的标识号JSESSIONID作为COOKIE的name添加到响应首部中返回给客户端;客户端下次访问时,请求首部中将携带该JSESSIONID,服务端将根据该JSESSIONID寻找与之配对的session,如果能找到对应的session,则直接操作该session资源,否则将重新为此JSESSIONID分配一个session和对应的缓冲区。

  使用Session技术需要解决如下三个问题:


  • (1).怎样获得属于某客户端的session对象(内存区域)?

  • (2).怎样向session中存取数据?

  • (3).session对象的生命周期?


3.1 获得Session对象

  服务端通过客户端发送COOKIE中的JSESSIONID区分客户端,可以通过请求包中的这个信息来获取该客户端相关的session信息。

HttpSession session = request.getSession();

  此方法有两个作用:


  • (1).从COOKIE中获取JSESSIONID,并寻找是否存在该ID对应的session对象。如果存在,则获取该session对象。

  • (2).如果该客户端没有发送JSESSIONID或JSESSIONID和服务端记录的ID值不匹配,则为该JSESSIONID重新分配一个session对象。

  实际上就是根据JSESSIONID判断该客户端是否在服务器上已经存在session了,有则用之,无则分配之。

3.2 向session中存取数据(session也是一个域对象)

  session也是一个域对象,session域的作用范围是整个session,可以对客户端的多次请求生效。该范围小于context域(即application域),大于request域(只在一次请求内有效)。

  作为域对象,session对象也同样具有如下三个方法:

session.setAttribute(String name,Object obj);
session.getAttribute(String name);
session.removeAttribute(String name);

 

  此外,可以通过session对象的getId()方法获取到该session的JSESSIONID值。

3.3 Session对象的生命周期



  • 创建:第一次执行request.getSession()时创建。当客户端访问带有getSession()方法的servlet时会执行该方法并创建session,访问jsp页面也会,因为jsp默认设置session=true会创建session。但访问静态资源(html/pic)等不会,因为输出这些静态数据的默认servlet不执行getSession()。

  • 销毁:

    • 1.服务器(非正常)关闭时。

    • 2.session过期/失效(默认30分钟,这个默认时间可以在web.xml中修改)。


      30

       

      需要注意的是失效时间的起算点,即从何时开始计算30分钟?从不操作服务器端的资源开始计时(即从最近一次读取session数据开始)。

    • 3.手动销毁session:session.invalidate();



  也就是说,客户端在一次会话中任何资源都共用一个session对象。

  问题:浏览器关闭,session就销毁了吗?
  不对,session存储在服务端,和客户端没多大关系,只要客户端没有操作session,等一段时间后,session自动销毁。但是,关闭浏览器后,COOKIE中的JSESSIONID就丢失了,也就无法再找到对应的session数据。可以在发送session给客户端前将jsessionid当成COOKIE的属性并配置COOKIE的持久化时间持久化到客户端磁盘,这样再次打开浏览器时jsessionid就不会丢失。代码大致如下:

HttpSession session = request.getSession();
session.setAttribute(
"username","Tom");
String id
= session.getId(); //获取JSESSIONID值
COOKIE COOKIE = new COOKIE("JSESSIONID",id); //"JSESSIONID"为固定值
COOKIE.setPath("/COOKIEDemo");
COOKIE.setMaxAge(
12*60*60); //JSESSIONID持久化保存12小时
response.addCOOKIE(COOKIE);
response.getWriter().write(
"JSESSIONID:"+id);
System.out.println(session.getAttribute(
"username"));

 


推荐阅读
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
author-avatar
lantian2502889907
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有