• Cookie和Session


    在这里插入图片描述

    今天我们来认识一下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 数据就会丢失.

    我们来画图理解一下吧
    在这里插入图片描述

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

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

    在这里插入图片描述
    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");
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    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);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

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

    这里的
    在这里插入图片描述
    这个sessonid来自创建的sesssion会话
    第二个请求
    在这里插入图片描述
    在这里插入图片描述

    这里就有cookie了
    在这里插入图片描述
    最后得到结果

    总结:实现登录的逻辑
    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存什么都可以

    这就是今天的全部内容了,我们下期再见了~~~
    在这里插入图片描述

  • 相关阅读:
    深入理解Redis分布式锁
    Spring Boot 程序优化的 14 个小妙招!
    【vue】使用computed时ts报错:Unexpected side effect in computed function.
    Java面试八股文宝典:初识数据结构-数组
    idea创建纯净的maven项目简单的maven工程
    【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-Chapter3-bash shell 基础命令
    IDEA代码重构技巧--拆分类
    Sodinokibi解密工具,可解密一千七百多个变种
    虚拟局域网VLAN_基础知识
    ubuntu中安装cheat
  • 原文地址:https://blog.csdn.net/weixin_61436104/article/details/131141223