Cookie和Session

一.回顾Cookie

Cookie是浏览器持久化存储数据的一个机制。我们知道,为了保证安全性,网页无法访问主机的文件系统,所以要想存储数据,就要通过其他方式,也就是这里的Cookie。

下面我们来讨论一下用cookie存储用户信息的情况:

假设一个情景去医院看病。首先要挂号,前台医生就会给每一位患者一张就诊卡,后需要想看医生,只要刷一下就诊卡,医生电脑里就能够显示患者的全部情况(基本信息,既往病例,账户余额……)。

这张就诊卡就相当于是每个患者的cookie,刷卡这个过程就是会通过医院的系统去查询对应的身份标识,从而得到完整的身份信息。

二.什么是Session,理解会话机制

上面说的每个患者的身份信息,都会存在医院的系统中。这些数据必然要存在数据库中,但又不单单是数据库中。在服务器代码的逻辑的执行过程中,这些数据也会被从库中查询出来,先临时保存到某个内存结构中,后续要是需要修改信息,就先修改该内存结构中的信息,再更新数据库。

这个内存结构就是所谓的Session,即会话。

会话的合集本质上就相当于是一个hash表,其中的key就是sessionID,value就是对应用户的身份信息

三.Cookie和Session的配合

Cookie是客户端存储数据的机制(持久化),Session是服务器存储数据的机制(非持久化,因为是一种内存结构),两者往往是相互配合使用:

在cookie中存放了用户身份标识,也可以理解成sessionID,多个用户的id可能是在同一个cookie中存放(因为一个网站是多个用户所共享的)但是,每一个用户都有独自的Session,这个session就是一个键值对结构,键就是sessionid,值就是用户信息。

所以同一个服务器会存放多个session,通过类似于hash表的结构组织起来

四.与cookie和session有关的api

Cookie是浏览器/客户端的机制,Session是服务器的机制,所以Servlet已经提供好了相关api供我们去使用

1.HttpServletRequest中的方法

HttpSession getSession(boolean )这个方法是在服务器中获取会话,参数如果为true,则当session不存在时就会新建一个会话;参数如果为false,则当会话不存在时仅仅返回null。Servlet通过HttpSession来表示一个会话。服务器上存有多个会话(类似于HashMap<String,HttpSession>,String就是sessionid,HttpSession就是session对象)这个方法主要是给登录场景使用,它就是拿着sessionid去查表。

Cookie[] getCookies()每个cookie都是一个键值对,cookie对象的属性就是key和value,key就是cookie的名,value就是该cookie的值

2.HttpServletResponse中的方法

void addCookie(Cookie cookie)把指定的cookie添加到响应中。

3.HttpSession中的方法

Session对象本身,就是键值对结构,这些键值对就是通过下面的两个Attribute(属性)方法完成的

1.Object getAttribute(String name)该方法返回在该会话中具有指定名称的对象(相当于时返回该用户的其中一个指定的信息)

2.void setAttribute(String name,Object value)该方法是个这个会话添加一个新的属性)

3.boolean isNew(),判定当前会话是否是新创建的会话

4.Cookie类中的方法

每个cookie就是一个键值对

1.String getName()返回当前cookie的名称(这个名称是之前响应中的Set-Cooki字段给浏览器设置的)

2.String getValue()获取该cookie的值

3.void setValue(String newValue)设置该cookie的值

五.代码实例:实现用户登录

Cookie/Session机制,很重要的作用就是辅助用户完成登录功能

先创建好项目login,注意目录结构,并且引入依赖,这里主要使用servlet的依赖

1.先编写一个登录页面

静态页面是放在webapp中的。在webapp中创建新的文件login.html,右键->opin in->explorer,再用vscode打开

首先生成html的框架,然后把title改成“登录”。然后在body中用form表单来触发浏览器发送请求给服务器从而实现登录

注意,action中的路径是不加/的

编写好后,点击右上角的edit configurations,点加号,点SmartTomcat,配置一下然后运行,这样就能看到一个登录页面了:

然后输入张三 123,用fiddler抓包,看看能不能抓到一个POST请求:

注意content-Type就是application/x-www-form-urlencoded

此处的登录也可以使用json,但是使用了json就需要通过ajax方法来构造请求

2.服务器处理上述请求

在java目录中,创一个新的包login,再创建一个新的类LoginServlet

注意,创建会话时传入true,他就hi根据请求中传入的cookie中的sessionid去查询hash表,从而找到对应的session对象。若cookie中没有sessionid或者sessionid没有查到对应的对象,这就说明没有登陆呢,然后就可创建出session对象(前提是true)。创建的同时也会制定好sessionid,把对象保存到hash表中,而把sessionid设置到响应中(在header中加上Set-Cookie字段)再传回给浏览器,让浏览器使用cookie保存sessionid。

最后登陆成功后的重定向操作就会触发发送get请求(请求index页面)

3.服务器处理重定向请求

既然要跳转到index页面,那就要生成一个主页,创建一个新的类IndexServlet

注意getAttribute方法的返回值是Object类型,所以要进行向下转型

到此为止,简单的登录逻辑就写完了,在浏览器上验证一下,用fiddler抓包,首先抓到一个get请求,是获取login.html

可是我们发现,这个里面的header里有一个cookie,其中就有一个JSESSIONID,这就奇怪了,这还没登陆呢,怎么就有sessionid了呢?先往下看:这个请求下面对应一个响应:

状态码是304,HTTP 304,有时也称为“304 Not Modified”,是一种与浏览器通信的代码:“自上次访问以来,请求的资源未被修改。”本质上,服务器告诉您的浏览器,自您最近一次访问该页面以来,浏览器中存储(缓存)的资源没有被修改。这就是因为刚才我们在这个浏览器上测试代码时已经登陆了一次了,所以已经存了id。先不管这个,我们再登陆一下,看看能不能抓到重定向响应以及发送的get请求,如下就是获取到的post请求和重定向响应以及get请求,以及get请求的响应:

但发现,最后一个响应报文的内容竟然不认识,这是因为浏览器是使用的GBK字符集,然而idea使用的utf8字符集,要想正确解析请求内容,就要在解析前将请求内容换成utf8编码,如下:

这回咱们用个别的浏览器,用谷歌的浏览器访问一下:

首先是一个get请求,请求获取到login.html以及响应返回页面,这次,get请求里面没有cookie这一项了,因为之前在谷歌浏览器没有访问过此页面,响应也不是304了。

然后输入用户名和密码,点击登录,抓包抓到了一个post请求:

这个请求的content-Type就是form表单(也就是正文类型)。

然后有一个它对应的响应:

注意,这是王五第一次登录,所以服务器这边没有他的session,所以就创建了它的session并且设置了id,然后通过响应将id返回给浏览器,也就是这里的Set-Cookie字段!!!同时,登录也会触发重定向,所以状态码是302,并且location是index

一点击登录就会触发页面跳转,就会给index路径发送一个get请求,如下是get请求及其响应:

注意这个get请求的cookie字段,它和刚才的set-cookie就是一样的!!

相关推荐

  1. cookiesession

    2024-04-05 17:08:06       56 阅读
  2. PHP cookieSessions

    2024-04-05 17:08:06       60 阅读
  3. 聊聊SessionCookie

    2024-04-05 17:08:06       63 阅读
  4. cookie+sessiontoken

    2024-04-05 17:08:06       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-05 17:08:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-05 17:08:06       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-05 17:08:06       82 阅读
  4. Python语言-面向对象

    2024-04-05 17:08:06       91 阅读

热门阅读

  1. Oracle备份和还原的几种方式

    2024-04-05 17:08:06       37 阅读
  2. 结 构 体

    2024-04-05 17:08:06       56 阅读
  3. 设计模式:适配器模式

    2024-04-05 17:08:06       35 阅读
  4. Git常用命令

    2024-04-05 17:08:06       27 阅读
  5. double二分(P3743 小鸟的设备)

    2024-04-05 17:08:06       41 阅读
  6. html网页设计项目实战--王者荣耀官网源码

    2024-04-05 17:08:06       31 阅读
  7. android wifi连接

    2024-04-05 17:08:06       43 阅读
  8. 【无标题】

    2024-04-05 17:08:06       38 阅读
  9. 物联网之传感器如何选型

    2024-04-05 17:08:06       36 阅读
  10. 宝塔 docker 安装 rabbitmq

    2024-04-05 17:08:06       34 阅读
  11. npm常用命令

    2024-04-05 17:08:06       36 阅读
  12. 什么是Android ABI?

    2024-04-05 17:08:06       32 阅读