🍀Cookie简介
HTTP协议自身是属于 "⽆状态"协议.
"⽆状态"的含义指的是:
- 默认情况下 HTTP 协议的客⼾端和服务器之间的这次通信,和下次通信之间没有直接的联系.但是实际开发中,我们很多时候是需要知道请求之间的关联关系的.
例如登陆⽹站成功后,第⼆次访问的时候服务器就能知道该请求是否是已经登陆过了.
上图中输入用户名和密码,点击登录之后,将这个登录请求发送给服务器,这个请求携带着用户名密码信息发送给服务器,服务器将用户名和密码进行存储(session),生成一个sessionId(sessionId对应session信息)返回给客户端,存于cookie中,访问其他页面时就可以携带cookie进行访问。
上述图中的"令牌"通常就存储在Cookie字段中. ⽐如去医院挂号
- 看病之前先挂号.挂号时候需要提供⾝份证号,同时得到了⼀张"就诊卡",这个就诊卡就相当于患 者的"令牌".
- 后续去各个科室进⾏检查,诊断,开药等操作,都不必再出⽰⾝份证了,只要凭就诊卡即可识别出当 前患者的⾝份.
- 看完病了之后,不想要就诊卡了,就可以注销这个卡.此时患者的⾝份和就诊卡的关联就销毁了.(类 似于⽹站的注销操作)
- ⼜来看病,可以办⼀张新的就诊卡,此时就得到了⼀个新的"令牌"
此时在服务器这边就需要记录"令牌"信息,以及令牌对应的⽤⼾信息,这个就是 Session 机制所做的⼯作
🎄理解Session
要理解Session,我们先来理解一下会话
在计算机领域,会话是⼀个客⼾与服务器之间的不中断的请求响应.对客⼾的每个请求,服务器能够识别出请求来⾃于同⼀个客⼾.
当⼀个未知的客⼾向Web应⽤程序发送第⼀个请求时就开始了⼀个会话.当客⼾明确结束会话或服务器在⼀个时限内没有接受到客⼾的任何请求时,会话就结束了.
⽐如我们打客服电话
每次打客服电话,是⼀个会话.挂断电话,会话就结束了
下次再打客服电话,⼜是⼀个新的会话.
如果我们⻓时间不说话,没有新的请求,会话也会结束
服务器同⼀时刻收到的请求是很多的.服务器需要清楚的区分每个请求是从属于哪个⽤⼾,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系.
Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象
Session的本质就是⼀个"哈希表",存储了⼀些键值对结构.Key 就是SessionID,Value就是⽤⼾信息(⽤⼾信息可以根据需求灵活设计).
SessionId 是由服务器⽣成的⼀个"唯⼀性字符串",从Session机制的⻆度来看,这个唯⼀性字符串称 为SessionId .但是站在整个登录流程中看待,也可以把这个唯⼀性字符串称为token .
上述例⼦中的令牌ID,就可以看做是SessionId,只不过令牌除了ID之外,还会带⼀些其他信息,⽐如时 间,签名等.
- 当⽤⼾登陆的时候,服务器在 Session 中新增⼀个新记录, 把 sessionId返回给客⼾端.(通过HTTP 响应中的 Set-Cookie 字段返回).
- 客⼾端后续再给服务器发送请求的时候,需要在请求中带上sessionId.(通过HTTP请求中的Cookie字段带上).
- 服务器收到请求之后,根据请求中的sessionId在Session信息中获取到对应的⽤⼾信息,再进⾏后续操作.找不到则重新创建Session,并把SessionID返回
Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失
🌳Cookie 和 Session 的区别
- Cookie 是客⼾端保存⽤⼾信息的⼀种机制.Session 是服务器端保存⽤⼾信息的⼀种机制.
- Cookie 和 Session之间主要是通过 SessionId 关联起来的, SessionId是 Cookie 和 Session 之间的桥梁
- Cookie 和 Session 经常会在⼀起配合使⽤. 但是不是必须配合
- 完全可以⽤ Cookie 来保存⼀些数据在客⼾端.这些数据不⼀定是⽤⼾⾝份信息,也不⼀定 是SessionId
- Session 中的sessionId 也不需要⾮得通过 Cookie/Set-Cookie 传递,⽐如通过URL传递
🌲获取Cookie
要想获取Cookie,首先得有Cookie,由于Cookie是存储在客户端的,所以可以伪造,我们就可以通过postman伪造Cookie。
postman伪造Cookie:
步骤一:
步骤二:添加domain(domain可以理解为IP或者域名,例如:127.0.0.1, www.jd.com)
步骤三 :添加Cookie,也是键值对的方式添加
此时Cookie就构造好了,可以在Header中查看
浏览器伪造Cookie:
伪造京东的Cookie,进入京东页面的开发者工具(F12):
通过上述操作,我们就构造好了Cookie,下面就通过代码来获取Cookie
在默认情况下,不管后端的接口是否会用到Cookie,前端在发送请求的时候,会把Cookie一起发送过来,那么服务器就只需要在请求里面拿取对应的Cookie即可。拿取Cookie有两种方式
🚩传统获取Cookie
有一个HttpServletRequest对象,和HttpServletResponse对象,这两个对象分别对应的是HTTP请求,HTTP响应,也就是整个HTTP请求里面有什么HttpServletRequest就有什么,整个HTTP响应有什么HttpServletResponse就有什么。这些信息都可以通过这两个对象获取出来,例如Cookie,User-Agent等信息。
Spring MVC是基于 Servlet API 构建的原始 Web 框架, 也是在Servlet的基础上实现的
HttpServletRequest , HttpServletResponse 是Servlet提供的两个类,是Spring MVC⽅法的内置对象.需要时直接在⽅法中添加声明即可.
HttpServletRequest对象代表客⼾端的请求,当客⼾端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的⽅法,可以获得客⼾端请求的所有信息.
HttpServletResponse 对象代表服务器的响应. HTTP响应的信息都在这个对象中, ⽐如向客⼾端发送的数据, 响应头,状态码等. 通过这个对象提供的⽅法, 可以获得服务器响应的所有内容
Spring MVC在这两个对象的基础上进⾏了封装, 给我们提供更加简单的使⽤⽅法.
在之前的操作中,我们获取参数就是自己定义一个类型来接收,此时我们就可以通过HttpServletRequest对象来获取参数。这也是传统的Servlet的做法,也就是Spring底层
代码:获取Cookie
通过浏览器发起请求:发现报了一个500服务器错误
查看服务器日志:出现了空指针异常,说明代码的30行某个值为null,通过观察代码发现,一定是cookies为null,在上述我们设置了京东的cookie,但是cookie不能跨域的,它只能作用在当前的domain下,所以我们访问的域名是127.0.0.1,这个域名我们是没有设置Cookie的,即cookie为null,那么在循环cookie之前,判断一下cookie是否为null即可
代码:
发起请求:
由于cookie中什么都没有,所以什么都没有打印,但是这个接口是访问成功了的
此时给当前domain添加cookie:
重新发起请求查看后端日志:
获取其中一个cookie对象:
发起请求查看后端日志:
🚩简洁获取Cookie
也有更简洁的方式获取Cookie,@CookieValue(),在括号里面填写你想要获取的key。
代码:
浏览器发送请求查看后端日志:
这个注解做的事情就是上述传统获取Cookie的内容,但是传统方式还是用的比较多一点
注意:
- 这个虽然获取更简单,但是一次只能获取你想要获取的参数,不能获取全部参数