文章目录
- 一、Cookie概念先知
- 1、Cookie是什么?
- 2、Cookie从哪里来?
- 3、Cookie要存到哪里去?
- 4、Cookie是存在哪里的?
- 5、浏览器是如何通过Cookie来记录的?
- 6、Cookie的过期时间有什么用?
- 二、见见Cookie
- 三、会话机制Session
- 四、理解Cookie和Session的区别【⭐】
- 五、核心方法介绍
- 六、实现用户登录【✔】
- 1、淘宝用户登录原理解说
- 2、模拟实现服务器响应用户登录请求
- 3、抓包及过程解析
- 4、整体交互过程梳理及代码
- 5、登录过程感性理解 —— 医院挂号🏥
- 八、疑难解惑
- 九、总结与提炼
一、Cookie概念先知
1、Cookie是什么?
对于Cookie来说,它是HTTP报文header头部中非常重要的一个属性,是浏览器提供给网页访问本地数据用的
💬 那此时就有同学疑惑了,难道浏览器可以随机地访问本地磁盘吗?这不是很危险?
- 这确实很危险,于是就规定了网页在打开的时候无法去访问本地的磁盘,否则用户打开一些恶意网站时就会造成磁盘数据被破坏的情况,那浏览器要如何去保存用户的信息呢?
- 此时就需要使用到Cookie了,网页提供了一种机制,使得网页可以通过Cookie去获取到用户的相关信息,但是不可以去直接访问用户的本地磁盘
所以总的来说,Cookie是浏览器提供的持久化存储数据的机制
2、Cookie从哪里来?
-
Cookie中的数据来自于服务器,服务器会通过HTTP响应的报头部分(set-Cookie字段),来决定要把啥样的信息保存到客户端这边去, 以及决定浏览器的Cookie要存什么~
-
通过HTTP响应的
Set-Cookie
字段,把键值对写回去即可
3、Cookie要存到哪里去?
最后要回到服务器这里,Cookie会在后续浏览器访问服务器的时候带回请求的header中发给服务器
💬 有同学问了,为什么要这么折腾呢?这样来回陶腾?
- 原因是服务器不是只给一个客户端提供服务,同一时刻要处理多个客户端,此时服务器就可以通过Cookie中的值来识别当前客户端是谁,当前客户端的服务提供到哪个环节了(客户端借助Cookie自报家门)
- 客户端这边会通过Cookie来保存当前用户使用的中间状态,当客户端访问浏览器的时候,就自动得把Cookie的内容带入到 请求(request) 中,此时服务器就能够知道现在客户端是什么样子了
4、Cookie是存在哪里的?
可以认为是存在于浏览器中的,存在于硬盘里的
- Cookie在存的时候,是按照
浏览器 + 域名
的维度来进行细分的,不同的浏览器有各自的Cookie,同一个浏览器不同的域名,对应不同的cookie。例如同一张网页,Google浏览器和火狐浏览器的Cookie都是不同的🌏
5、浏览器是如何通过Cookie来记录的?
- 当浏览器保存好Cookie后,再给服务器发送请求的时候,就会带上之前所存在的Cookie,它就像服务器在浏览器这边搞的寄存器一样,拥有一定的【记忆存储功能】
- 但和保存聊天记录又是不同的概念,而且浏览器中的保存账号密码和http没有多大联系
6、Cookie的过期时间有什么用?
Cookie里面的内容不光是键值对,同时还有过期时间,到一定时间就会自动过期
- 有些公共的电脑,比如学校图书馆中的电子阅览室中的那些,在这些电脑上可以登录自己的账号,然后登录状态就会保存到Cookie中了
- 但是在下次再来使用的时候,Cookie可能就过期了,就需要重新登录,越是敏感(和钱相关)的网站,过期时间就越短,道理很简单,如果你在一台公共电脑中登录了自己的淘宝账号去买东西,在你下机之后另一个人也可以继续使用你的账号,此时就会变得非常危险
二、见见Cookie
了解了Cookie的基本概念后,我们来见见Cookie
- 例如我现在打开CSDN的这个网站,然后点击网址中的🔒,就可以看到我这个浏览器中的一些Cookie值了
- 接着继续点击去,就可以看到在Cookie存放的一些具体内容,也就是我在登录一些网站之后所留下的一些个人信息
除了可以直接在浏览器中找到Cookie,而且可以看到里面存放的用户信息,但是具体的内容是什么呢?这些是可以由我们程序员来自定义的。这样,我们通过抓包来看看👈
- 通过抓包可以看出,header头部中的Cookie所保存的内容是一堆很奇怪的内容,具体这些内容所代码的含义是什么呢?这个我也不知道,上面说过了,这是由程序员来自定义的,这一块可以在我后面介绍了
HttpSession
后再做深入,这里了解一下即可
三、会话机制Session
知道了什么是Cookie,接下去我们来说说会话机制Session,它又是个什么东西呢?
- 服务器同一时刻收到的请求是很多的. 服务器需要清除的区分清楚每个请求是从属于哪个用户, 就需要在
服务器这边记录每个用户【令牌】以及用户的信息的对应关系 - 具体地可以先看看下面这张图,当一个客户端去访问服务器的时候,就会带有一个【token】,我们也把它称作为
sessionId
,是服务器这边分配给每一个用户的,当服务器这边保存了每个用户的相关信息后,下次再登录的时候就不需要再输入用户名和密码,服务器只需要根据这个id去进行查询即可
- 可以看到,当用户登陆的时候, 服务器在 Session 中新增一个新记录, 并把 sessionId / token 返回给客户端. (例如通过 HTTP 响应中的 Set-Cookie 字段返回)
- 客户端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId/ token. (例如通过 HTTP 请求
中的 Cookie 字段带上) - 服务器收到请求之后, 根据请求中的 sessionId / token 在 Session 信息中获取到对应的用户信息, 再进行后续操作
- 上面的这些sessionId和每个用户的信息构成一个键值对,用户的信息又单独构成一个键值对,例如:姓名是什么、年龄是什么、账户余额是什么?
💬 可能在看了上面这些后你对会话Sesion还不是很了解,不过没关系,后面我在使用代码讲解用户登录的时候就会一目了然了~
四、理解Cookie和Session的区别【⭐】
接下去我们来看看Cookie和Session之间的区别
-
Cookie是客户端的存储机制,Session是服务器的存储机制
-
Cookie里面可以存各种键值对(还可以存别的);Session则专门用来保存用户信息
-
Cookie完全可以单独使用,不搭配Session(实现非 登录 场景下);Session也可以不搭配Cookie使用.(手机app登录服务器,服务器也需要Session,此时就没有Cookie的概念),Cookie跟浏览器强相关的~
-
Cookie 是属于HTTP协议中的一个部分,Session 则可以和HTTP无关(TCP、websocket…也可以用session)
💬 上面的这些,你可以认为是大家口中所述的 “八股文”,但是光这么背一定没什么效果的,主要在于理解,在理解了Cookie和Session的交互机制后再来看这些东西你会发现根本不需要背
五、核心方法介绍
然后我们来讲一下后面再模拟实现Cookie和Session机制时的一些核心方法,也就是我们所说的API
HttpServletRequest 类中的相关方法
方法 | 描述 |
---|---|
HttpSession getSession() | 在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null |
Cookie[] getCookies() | 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对. |
HttpServletResponse 类中的相关方法
方法 | 描述 |
---|---|
void addCookie(Cookie cookie) | 把指定的 cookie 添加到响应中 |
void sendRedirect(String location) | 使用指定的重定向位置 URL 发送临时重定向响应到客户端 |
HttpSession 类中的相关方法
一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息
方法 | 描述 |
---|---|
Object getAttribute(Stringname) | 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null |
void setAttribute(String name, Object value) | 该方法使用指定的名称绑定一个对象到该 session 会话 |
boolean isNew() | 判定当前是否是新创建出的会话 |
Cookie 类中的相关方法
每个 Cookie 对象就是一个键值对
方法 | 描述 |
---|---|
String getName() | 该方法返回 cookie 的名称。名称在创建后不能改变。(这个值是 Set-Cooke 字段设置给浏览器的) |
String getValue() | 该方法获取与 cookie 关联的值 |
void setValue(StringnewValue) | 该方法设置与 cookie 关联的值 |
💬 上面的这些方法,我们在下面进行【用户登录】的时候会用到三四个,不需要全部都记住
六、实现用户登录【✔】
1、淘宝用户登录原理解说
- 对于淘宝相信很多同学都用过,可以在上面买一些东西,但是你知道我们在访问淘宝页面的时候是如何与后端的服务器进行交互的吗?
这里我画了一张交互图,可以通过这张图来分析浏览器页面与淘宝后端服务器的这个交互过程
- 首先当我们浏览器点击淘宝主页链接的时候,我们就可以看到这个主页的样子,此时就是与服务器进行的第一次交互,即发送了一个GET请求去获取到当前的这个HTML页面,接着服务器收到这个请求后就将淘宝的主页展示给我们,不过此时服务器是不知道我们的身份信息的
- 第二次交互就是在我们进行登录的时候了,此时我们点击网页中的【登录】按钮输入自己的用户名和密码,你可以认为这是一个表单,那此时我们发起的就是一个POST请求,此时当服务器接收到这个请求后获取到用户输入的这些信息,进行一个校验和判断,若是用户输入的信息正确的话(已经注册过),此时服务器就会生成一个sessionId,将此id封装在HTTP响应报文中进行返回,并且在自己这里新建一个会话Session去保存用户的相关信息,后续服务器只需要通过这个sessionId去进行判断即可
- 当服务器返回登录成功的提示信息给到用户后,浏览器这边也会同时将服务器存放在响应报文中的SessionId / token存放在【Cookie】中,这也就是为什么我们的Cookie中为什么可以保存这么多东西了
- 但是淘宝不仅仅只有一个主页,而是由多个页面所构成的,所以当用户在访问淘宝的其他页面时间,又会向服务器发送请求,此时是
GET请求
,服务器再收到请求后进行判断当前这个用户是否已经登录过,通过获取到当前用户所携带的sessionId进行判断,当前若是这个id == null
的话表示当前用户还未登录,需要先去进行一个登录;如果已经登录过的话就会相关的网页显示给用户
- 上述的这么一个交互过程,就是Cookie和Sessiond的这么一个交互逻辑,服务器通过给每一个登录进来的用户创建一个新的会话,并且为其分配一个身份的序号,将其作为key值,那么这个用户相对应的信息就作为value值,你可以把它看作是一个【哈希表】的结构,存放的都是一个个键值对
- 每一个会话都是一个键值对,会话中每个用户的相关信息又是一个键值对,是一个HttpSession对象。在后续的请求中的,服务器收到相关的Cookie中的身份序号,就会根据这个序号去查询上述的哈希表,来判断是哪一位用户。如果查到了,就知道当前用户是谁,无需再重新输入密码,增加了效率也方便了用户
💬 可能你还不懂什么是HttpSession对象,下面我会通过一个例子去进行陈述
2、模拟实现服务器响应用户登录请求
需求分析
首先来讲一下这个模拟实现前后端需要分别准备的工作
① 前端:一个登录页面,一个主页面
② 后端;两个Servlet,一个是处理登录的loginServler
,判断输入的用户名或密码是否正确;另一个是构造主页面的indexServlet
- 首先的话是供用户输入信息的表单,用于向服务器发送POST请求
<form action="login" method="post">
<label>用户名:</label>
<input type="text" name="userName"><p></p>
<label>密码:</label>
<input type="text" name="passWord"><p></p>
<input type="submit" value="登录">
</form>
接下去是后端的这一块登录逻辑,主要来分析一下这里
- 首先的话是要获取到用户输入的内容信息
String userName = req.getParameter("userName");
String passWord = req.getParameter("passWord");
- 然后便是去进行相关的逻辑判断,看看输入的信息是否合法,这边我给出了两种写法,第一种写法比较直观易懂一些,就是使用逻辑或
||
去做一个判断,但是我平常在写代码逻辑的时候一般都是以第二种写法,防止产生if的嵌套
/**
* 判断用户输入的用户名和密码是否正确
*/
// if(useName.equals("zhangsan") || passWord.equals("lisi")){
// if(passWord.equals("123456")){
// // 登录成功
// }else{
// // 登录失败
// }
// }else{
// // 登录失败
// }
if(!userName.equals("zhangsan") && !userName.equals("lisi")){
// 登录失败
// 1.打印日志
System.out.println("用户名错误");
// 2.重定向
resp.sendRedirect("login.html");
return;
}
if(!passWord.equals("123456")){
// 登录失败
// 1.打印日志
System.out.println("密码错误");
// 2.重定向
resp.sendRedirect("login.html");
return;
}
- 这个
sendRedirect()
就是我们在上面介绍到的HttpServletResponse中的一个方法,用于去进行一个【重定向】的操作,使用户名或者密码输入错误的用户回到登录页面继续输入
resp.sendRedirect("login.html");
- 如果上述条件都不满足的话代表就是登录成功,此时在服务端这边就会为当前用户创建一个SessionId,以返回给用户做下一次的校验。
- 并且还会在自己这里为当前用户创建一个会话,这里用到了HttpServletRequest中的
getSession()
方法,可以看到我为其传入了一个参数为【true】,代表若是这个SessionId存在的话就会返回一个HttpSession的对象,此时我们就可以手动地为这个对象去设置参数,那就是使用到 HttpSession 中的setAttribute()
方法,所以说这里面的东西可以由我们程序员来进行自定义
// 登录成功
// 1.创建一个会话【所谓的会话就是一个键值对, key是sessionId, value是HttpSession对象】
HttpSession httpSession = req.getSession(true);
// 2.将当前登录的用户名保存到会话中,HttpSession所构建对象的value值也是一个 map 结构
httpSession.setAttribute("userName", userName);
httpSession.setAttribute("passWord", passWord);
httpSession.setAttribute("loginCount", "0");
- 因为这一块涉及键值对的嵌套,比较难理解一些,读者可以通过这张图来帮助理解,每个会话即对应一个客户端,而且它是一个键值对的形式,SessionId为【key】,HttpSession为【value】,而且其内部保存用户的信息也是一个键值对的形式,可以由我们程序员来自己定义
// 3.重定向到主页
resp.sendRedirect("index")
👉 最后的这一句要和indexServlet这个类合起来说,因为此时已经为用户创建好了一个会话,此时当前的这个loginServlet的工作已经做完了,接下去我们要模拟的就是用户拥有这个SessionId后去进行登录时与服务器产生的第二次交互。当然这里你可以去再实现一个页面然后重定向到这个页面,这边我就直接通过@WebServlet
注解去进行一个转交了
@WebServlet("/index")
- 然后便是这一块的逻辑,如果用户一开始在访问主页的时候没有进行过登录,那此时他是不会有这个SessionId的,那便需要用户先去进行一个登录的操作,可以看到这边的
getSession()
我传入的false,此时就不会去新建一个会话,而是直接返回null,我们便可以根据这个来判断,打印日志并回到登录页面让用户先行登录 - 若是用户已经登录的话表明服务器获取到它的SessionId了,那就表明当前用户之前已经登录过,此时我们要执行的逻辑就是去构造一个http界面然后欢迎用户,不过在这之前你一定发现我多做了一些事,那就是设置了一个
loginCount
,在每次判定当前用户确实存在时,就取出这个loginCount
,不过我们是以字符串的形式存放进去的,那么拿出来的话进行计算的话就要用整数的形式进行操作,所以这边用到了一个Integer.parseInt()
,每次当前用户登录进此页面的时候它的访问此处就 + 1 - 最后的话我们再将当前用户的相关信息构建成一个HTML页面显示在浏览器上,注意这个页面是我们自己构造出来返回给用户的,而不是早已经有的
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
HttpSession httpSession = req.getSession(false);
// 1.首先根据用户名判断当前用户是否登录过
if(httpSession == null){
// 说明该用户还未登录,提示登录
System.out.println("您还未登录,请重新登录");
resp.sendRedirect("login.html");
return;
}
// 2.表明用户登录过,根据根据sessionId,显示欢迎界面
String userName = (String)httpSession.getAttribute("userName");
String CountString = (String)httpSession.getAttribute("loginCount");
int loginCount = Integer.parseInt(CountString);
loginCount += 1;
httpSession.setAttribute("loginCount", loginCount + "");
// 构造页面
StringBuilder html = new StringBuilder();
html.append(String.format("<div>用户名:%s</div>", userName));
html.append(String.format("<div>登录次数:%d</div>", loginCount));
resp.getWriter().write(html.toString());
}
3、抓包及过程解析
在看了上面的代码后,可能你会觉得很简单,因为现在有了像【Spring Boot】这样的成熟框架后几乎没什么人学Servlet了,但是我要介绍得是这种思想,读者要注重理解我所讲解的这种思想
- 首先我们启动Tomcat服务器,然后进入登录页面输入用户名和密码
- 若此时用户名和密码输入有误的话就会回到登录页面让用户去进行重新输入
- 只有当输入正确的用户名和密码后,浏览器才会构造出欢迎界面
- 此时我们顺手通过Fiddler去抓包观察,就可以观察到前后端其实进行了两次交互,一次访问的是
login
这个接口,另外一次访问的则是index
这个接口,也说明前端向后端发起了两次请求
- 然后来看第一次所发起的POST请求,通过【手撕】了一下这个报文,知晓了它都是由哪些内容构成的,这个相信读者应该很熟悉了,不过要注意的第一点是:此次的请求中是不带有Cookie的,因为这是我们第一次去访问这个页面,此时服务器哪里还没有为我们新建一个会话,所以然后没有分配一个SessionId
- 然后来看到服务器对于上面的这次请求所发回的响应看到有一个Set-Cookie字段,看到最前面有个
JSESSIONID
,这其实就是服务器给当前用户创建了一个临时会话并分配一个SessionId - 不仅如此,还去进行了一个重定向,跳转到了我们第二个
@WebServlet()
的注解处
resp.sendRedirect("index");
- 当第一次请求完成后,当前用户就有一份SessionId,相当于是一个令牌,之后发起的第二次请求,我们就要去构造出一个HTML页面,返回给用户,所以用户发送的是GET请求,经过上面的【重定向】,我们跳转到了
@WebServlet("/index")
这里 - 并且在此次的请求中,我们看到了Cookie,也就是上面服务端为其构造出来的一个身份标识
- 此次的请求,服务端会为其做出处理,因为我们在
getSession()
中传入的是【false】,所以当用户不存在的时候就会返回null,我们就靠其来进行一个判断,是否要让用户进行登录的操作 - 最后的话就是服务器对于上面一次的请求发回的响应因为有了下面这句话的存在,所以我通过
resp
对象返回给浏览器的所有响应都会被视为HTML中的元素,所以有些同学可能疑惑这里为什么会有<div>
resp.setContentType("text/html;charset=utf-8");
- 然后我们再去访问的话就可以看到HTTP请求报文中就带有了Cookie字段,里面存放的便是服务端为当前用户所专门构造的身份识别令牌
- 而且后续再去进行多次登录的时候,我们前面所设置
loginCount
就起到作用了,它会记录下每个用户的登录次数,也是一种键值对的形式进行组织
4、整体交互过程梳理及代码
上面是边抓包和代码一起进行分析,最后的话我们再来梳理一下整体的交互逻辑
然后再看看整体代码
login.html
<form action="login" method="post">
<label>用户名:</label>
<input type="text" name="userName"><p></p>
<label>密码:</label>
<input type="text" name="passWord"><p></p>
<input type="submit" value="登录">
</form>
loginServlet.java
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userName = req.getParameter("userName");
String passWord = req.getParameter("passWord");
/**
* 判断用户输入的用户名和密码是否正确
*/
// if(useName.equals("zhangsan") || passWord.equals("lisi")){
// if(passWord.equals("123456")){
// // 登录成功
// }else{
// // 登录失败
// }
// }else{
// // 登录失败
// }
if(!userName.equals("zhangsan") && !userName.equals("lisi")){
// 登录失败
// 1.打印日志
System.out.println("用户名错误");
// 2.重定向
resp.sendRedirect("login.html");
return;
}
if(!passWord.equals("123456")){
// 登录失败
// 1.打印日志
System.out.println("密码错误");
// 2.重定向
resp.sendRedirect("login.html");
return;
}// 登录成功
// 1.创建一个会话【所谓的会话就是一个键值对, key是sessionId, value是HttpSession对象】
HttpSession httpSession = req.getSession(true);
// 2.将当前登录的用户名保存到会话中,HttpSession所构建对象的value值也是一个 map 结构
httpSession.setAttribute("userName", userName);
httpSession.setAttribute("passWord", passWord);
httpSession.setAttribute("loginCount", "0");
// 3.重定向到主页
resp.sendRedirect("index");
}
}
indexServlet.java
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
HttpSession httpSession = req.getSession(false);
// 1.首先根据用户名判断当前用户是否登录过
if(httpSession == null){
// 说明该用户还未登录,提示登录
System.out.println("您还未登录,请重新登录");
resp.sendRedirect("login.html");
return;
}
// 2.表明用户登录过,根据根据sessionId,显示欢迎界面
String userName = (String)httpSession.getAttribute("userName");
String CountString = (String)httpSession.getAttribute("loginCount");
int loginCount = Integer.parseInt(CountString);
loginCount += 1;
httpSession.setAttribute("loginCount", loginCount + "");
// 构造页面
StringBuilder html = new StringBuilder();
html.append(String.format("<div>用户名:%s</div>", userName));
html.append(String.format("<div>登录次数:%d</div>", loginCount));
resp.getWriter().write(html.toString());
}
}
5、登录过程感性理解 —— 医院挂号🏥
然后我们通过一个生活中的小案例去再度理解一下这个交互的过程,帮助读者进一步有更好的理解
其实对于上面的这么一个登录过程,可以和我们在医院看病的这么一个流程很相似。
- 首先我们到达医院,要拿着身份证🆔先去挂号,办理就诊卡,此时就是我们第一次进行登录的时候,需要为我们当前和这个用户创建会话并分配SessionId,那对应到医院这里就是在挂号系统中新增一个用户然后会自动为你生成一个编号,给你一张【就诊卡】,然后你的信息就进入医院的系统了,这张【就诊卡】就是你在医院的身份象征,到哪里你都要带着它
- 然后的话我最近身体有些地方不太舒服,所以打算挂个内科看看,那此时我就先到了内科的诊室。但是医生无法平白无故地给我看需要提供一些依据他才可以诊断我到底哪里出问题了,所以他会先让我去抽个血、拍个片之类的,此时呢就给我的【就诊卡】中写入了一些信息,让我去某某科室先进行一些其他的检查,这里其实就是给HttpSession设置了一些
attribute
- 那此时我去就【化验科】验血去了,那么那边的医生也需要我先出示就诊卡她才能给我抽血,否则不能平白无故地给我验,当我抽完血后,登上一段时间(可能要很久),就可以去拿单子了,回忆一下你在拿单子的时候是不是也要出示就诊卡,此时你的卡中又会多出一些信息,也就是也设置了一些
attribute
- 验完血后接着去【放射科】,此时你也要先把就诊卡给到那边的医生/护士,它们才知道要给你拍X光还是CT,又或者是磁共振,当你拍完去取片子的时候也是一样,你的卡里也会多出来细一些信息
- 最后医生就会通过读取我卡中的拍摄记录然后去诊断我到底是哪里出了问题,最后的话再告诉就诊结果以及要平常应该注意些什么、吃I些什么药物可以治疗,此时也会往我的就诊卡中写入一些信息
- 对于上面每一次的刷卡,都是通过我的SessionId去系统中进行查询,进一步得到里面的
attribute
,知道要做哪些检查和结果是什么。所以我们的这张就诊卡其实就相当于是Cookie,里面存放了你自己的身份表示信息SessionId,如果有这张卡的话再进出其他科室的时候就无需再告诉医生你叫什么,是从哪里过来的了,直接一刷卡就行 - 当然上面也说过Cookie也会丢失、也会过期,即我们的就诊卡可能也会损坏、丢失,那下次去医院的时候就需要重新办理一些相关的手续获取一个新的SessionId即你专属的【就诊卡】
八、疑难解惑
看完了用户登录这个案例,你是否对Cookie和Session的理解更上一层楼了呢?接下去我再把同学们遇到的一些疑惑解答一下
💬 刚才getSession()中所传递的【true】和【false】还有些不太明白,可以再解释一下吗?
- 对于
getSession()
来说,它是HttpServletRequest类的一个方法,传入【true】的话,在判定其返回值时,如果存在就返回现成的,如果不存在的话就创建一个新的,一般我们放在用户初次登录的时候;传入【false】的话,存在也会返回现成的,但若是不存在的话就返回null,一般我们放在用户已经存在的时候
💬 如果在一个浏览器中开同一个标签页进行登录,假设两个标签页所登录的账号是不同的,那在第二个标签页进行登录的时候是否会把第一个标签页中SessionId所对应的HttpSession对象给改了呢?
- 这个是不会的,因为同一个网页是做不到同时登录两个用户的,因为你开的这两个页面用的是同一个Cookie,共用同一个登录状态,所以是无法进行兼容的,一次只能有一位用户进行登录
💬 追问:如果开无痕模式呢?
- 这个就不一样了,对于无痕模式而言,它是有一套自己的Cookie的, 和其他页面的Cookie不混淆,因为浏览器进行了特殊的处理,所以我们在上网查询一些 “学习资料” 的时候就很方便了
💬 一个域名可以同时有两个Cookie?
- 这个当然是可以的,还记得上面我们看的Cookie吗,足足有90多个,一个网页是可以对应多个Cookie的,但是SessionId只能有一个,是作为访问服务器的唯一身份标识
💬 有没有办法让两个标签页不用同一个SessionId呢?
- 不用Cookie就可以了~~当我们在实现保存用户信息的时候,是可以使用其他手段的,不一样非要使用到Cookie的,基于Cookie去进行存放是一个当前比较流行的实现方式,让浏览器进行一些本地的存储是有其他方式的,例如:LocalStroage(存键值对)、IndexDB也可以存放用户信息,让不同的页面存储不同的SessionId即可
九、总结与提炼
最后来总结一下本文所介绍的内容📖
- 首先我们了解了什么是Cookie以及它的一系列相关概念,见到了Cookie长什么样,知晓了它有什么作用,然后便了解了一下会话机制Session,知道了在服务器同时接受多个浏览器的访问时需要通过SessionId来进行相应的识别,此时会为每一个接入用户创建一个新的会话来进行存放,构造好用户的对应信息后就可以在后面用户再度接入时通过搜索相关的SessionId去进行一个精准地查询
- 当然,Cookie和Session也是面试中常考的一个知识点,会让你去区分一下它们之间的区别在哪里,然后这要建立在你已经理解它们之间交互逻辑的基础上,这点是很重要的
- 所以接下去,我就通过一个【用户登录】的案例带你理解了前后端之间交互地这么一个逻辑,双方是如何进行一发一收的,重点是在于理解会话Session的建立以及SessionId的分配、判定用户是否登录的逻辑,如果不清楚的可以看我话的交互图,再捋一遍思路,就能明白Cookie和Session的作用到底在哪里
- 最后我也通过了一个生活中的小案例 —— 医院挂号来帮助理解,希望看完了这个案例后你能对Cookie和Session的理解更上一层楼
以上就是本文要介绍的所有内容,感谢您的阅读🌹