Cookie和Session

Cookie和Session_第1张图片

今天我们来认识一下Session

1.回忆Cookie

2.认识Session(会话)

1.利用Session模拟实现登录功能

2.登录逻辑的固定套路

3.Cookie和Session区别

1.回忆Cookie

我们之前已经学习过了cookie机制
Cookie是浏览器在本地存储数据的一种机制
1.cookie从哪里来
cookie是从服务器来的
服务器在响应中会带有Set-Cookie字段,通过这个字段就可以把要把保存在浏览器本地的数据给返回回去
2.cookie到哪里去
后续浏览器访问服务器的时候,会把当前本地所有的cookie都通过http请求给带过去

3.cookie有啥用
最典型的应用就是用Cookie保存当前用户的登录状态

2.认识Session(会话)

而在Cookie保存用户身份标识这类的应用场景,身份标识如何分配,以及身份信息具体如何存储,都是需要服务器的支持的
那么这个时候用啥来实现用户区分呢?
用Session(会话)
Session既是服务器用来实现用户身份区分的一种机制,通常和Cookie配合使用
Session是给当前的用户分配一个sessionId,同时记录当前用户的身份信息
sessionId就会被返回浏览器的cookie中,后续浏览器访问服务器就会带着这个sessionId,从而让服务器识别当前用户的身份
会话的本质就是一个 “哈希表”, 存储了一些键值对结构. key 就是令牌ID(token/sessionId), value 就是用户信息(用户信息可以根据需求灵活设计).
Servlet 的 Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.

我们来画图理解一下吧
Cookie和Session_第2张图片

1.当用户登陆的时候, 服务器在 Session 中新增一个新记录, 并把 sessionId 返回给客户端. (例如通过 HTTP 响应中的 Set-Cookie 字段返回).
2.客户端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId (例如通过 HTTP 请求中的 Cookie 字段带上).
服务器收到请求之后, 根据请求中的 sessionId 在 Session 信息中获取到对应的用户信息,
再进行后续操作.

1.下面来认识一下Session的方法

方法 描述
HttpSessiongetSession() 在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null
Cookie[]getCookies() 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对.

getSession有一个参数,boolean类型的,
如果参数为false,getSseeion的行为是
1.读取请求中Cookie的sessionId
2.在服务器这边根据sessionId查询对应的Session对象
3.如果查到了,就会直接返回这个session对象,如果没查到,返回null

如果参数为true,getSession的行为是:
1.读取请求中Cookie的sessionId
2.在服务器这边根据sessionId查询对应的Session对象
3.如果查到了,就会直接返回这个session对象
4.如果没查到,会创建一个Session对象,同时生成一个sessionId,以sessionIdkey,Session对象为value,把这个键值对存储到服务器里的一个hash表中,同时把sessionId以Set-Cookie的方式返回给浏览器

2.下面我们来模拟实现登录功能
需要两个页面
1.登录页(包含两个输入框,用户名和密码,还要有一个登录按钮)
点击登录,发起http请求
服务器处理这个请求的时候验证用户名密码
如果都是对的,就跳转到主页
2.主页
主页单纯的显示当前的用户名,是一个动态页面(欢迎xxx)
登录页就是一个HTML
还需要一个Servlet,实现登录时候的用户名密码校验
还需要一个Servlet来生成主页(主页的内容是动态的,)

开写

1.先写登录页的前端页面

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta namen="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面title>
head>
<body>
    <form action="login" method="post">
            <input type="text" name="username">
            <input type="password" name="password">
            <input type="submit" value="登录">
    form>
    
body>
html>

Cookie和Session_第3张图片

form表单会组织这里的数据以键值对的形式提交给服务器
key就是input的name属性,
value就是input用户输入的内容
最终构造成post请求以键值对的形式进行组织
服务器通过getParameter来获取指定key的value

Cookie和Session_第4张图片
2.编写login.HTML,处理登录请求
规定登录请求格式
POST/login
Content-Type:application/x-www-form-urlencoded

user=zhangsan&password=123
登录请求一般都用post
2.编写LoginServlet处理上述登录请求

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-10
 * Time: 14:53
 */
//这个Servlet用来实现登录时的校验
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.从请求拿到用户名密码
        //为了保证读出来的参数也支持中文,设置请求编码方式为utf8
        req.setCharacterEncoding("utf8");
        String  username=req.getParameter("username");
        String  password=req.getParameter("password");
        //2.验证用户名密码是否正确
        if(username==null||password==null||username.equals("")||password.equals("")){
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前用户名或密码不能为空");
            return;
        }
        //此处假设用户名只能是zhangsan 或者wangyibo,密码都是123
        //正常的登录逻辑,验证用户名密码都是从数据库读取的,此处为了方便,就不用了
        if(!username.equals("zhangsan")&&!username.equals("wangyibo")){
           //用户名有问题
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前用户名或密码有误");
            return;

            }
        if (!password.equals("123")){
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前用户名或密码有误");
            return;

        }
        //3.用户名和密码验证成功,创建会话
        //当前用户处于未登录状态,此时请求的cookie没有sessionId
        //此时的getSession无法从服务器的哈希表找到该session对象
        //由于此处把参数设置为true,所以允许getSession创建Session对象和sessionId
        //然后会自动把sessionId和session对象存储到哈希表中,
        //同时返回这个session对象,并且在接下来的响应中把这个sessionId返回给客户端浏览器

        HttpSession session=req.getSession(true);
        //让session存储自定义数据,存储用户信息
        session.setAttribute("username",username);
        //4.登陆成功之后,自动跳转到主页
        resp.sendRedirect("index");


    }
}

3.编写主页的代码

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-10
 * Time: 14:55
 */
//这个类用来实现动态生成主页面
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //此处禁止创建会话,如果没找到,认为用户是未登录的状态
        //如果找到了,才认为是登录状态
        HttpSession session=req.getSession(false);
        if(session==null){
            //当前未登录
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前用户未登录");
            return;
        }
        String  username=(String)session.getAttribute("username");
        //虽然有会话对象,但是没有属性,也认为是登录状态异常
        if(username==null){
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前用户未登录");
            return;
        }

        //如果都没问题,生成动态页面
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("欢迎你!"+username);
    }

}

我们的代码就写完了,来看一下结果
Cookie和Session_第5张图片
抓包来看看代码执行流程
在这里插入图片描述
Cookie和Session_第6张图片
这里是没有cookie的,点击登录,触发一个登录请求
Cookie和Session_第7张图片
Cookie和Session_第8张图片
第一个请求的响应有set-cookie

这里的
Cookie和Session_第9张图片
这个sessonid来自创建的sesssion会话
第二个请求
Cookie和Session_第10张图片
Cookie和Session_第11张图片

这里就有cookie了
Cookie和Session_第12张图片
最后得到结果

总结:实现登录的逻辑
1.读取用户名和密码
2.验证用户名密码
3.创建会话,保存必要信息
4.重定向到主页

上述的sessionId不会一直存在下去,当服务器重新启动的时候.原来hash表中的内容就没了
这时再次访问可能sessionId无法查询到,那么就是未登录状态
因为session默认保存在内存中
不过如果是Smart Tomcat,为了方便我们调试,可能会把会话持久化,这个要看smart Tomcat的版本
如果是手动部署到Tomcat,那会话还是默认保存在内存,重启会丢失
这里说一个小问题,为什么smart Tomcat不用打包就可以执行
解答:
smart tomcat会自动配置。通过target目录 和webapp目录访问
3.cookie和session的区别
1.Cookie 是客户端的机制. Session 是服务器端的机制.
2.Cookie 和 Session 经常会在一起配合使用. 但是不是必须配合.
3.完全可以用 Cookie 来保存一些数据在客户端. 这些数据不一定是用户身份信息, 也不一定是token / sessionId
4.Session 中的 token / sessionId 也不需要非得通过 Cookie / Set-Cookie 传递
5.session主要是来存用户的相关数据,cookie存什么都可以

这就是今天的全部内容了,我们下期再见了~~~
Cookie和Session_第13张图片

你可能感兴趣的:(servlet,服务器,前端)