0
点赞
收藏
分享

微信扫一扫

Cookie 和 Session、实现用户登录逻辑

拾光的Shelly 2023-01-04 阅读 58

Cookie 和 Session

一、回忆 Cookie

在讲 HTTP 协议时,我们曾提到过 Cookie:https://blog.csdn.net/yyhgo_/article/details/128433565?spm=1001.2014.3001.5501

HTTP 协议自身是属于 “无状态” 协议。

但是实际开发中,我们很多时候是需要知道请求之间的关联关系的

Cookie 就是浏览器在本地存储数据的一种机制 (存到硬盘上)。

Cookie 中存储了一个字符串,这个数据可能是客户端 (网页) 自行通过 JS 写入的,也可能来自于服务器 (服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据)!

在这里插入图片描述
在这里插入图片描述

查看Cookie:
在这里插入图片描述
在这里插入图片描述

  • Cookie从哪儿来?
    Cookie是存在浏览器的,来源是服务器。
    在这里插入图片描述
  • Cookie到哪儿去?
    在这里插入图片描述

二、理解会话机制 (Session)

服务器同一时刻收到的请求是很多的。服务器需要清除的区分清楚每个请求是从属于哪个用户,就需要在服务器这边记录每个用户令牌以及用户的信息的对应关系。

会话的本质就是一个 “哈希表”,存储了一些键值对结构。key 就是令牌的 ID(token/sessionId),value 就是用户信息 (用户信息可以根据需求灵活设计)。

在这里插入图片描述

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

在这里插入图片描述

三、Cookie 和 Session 的区别

Cookie 是客户端的机制;Session 是服务器端的机制。
Cookie 和 Session 经常会在一起配合使用 (并不是必须)。
完全可以用 Cookie 来保存一些数据在客户端,这些数据不一定是用户身份信息,也不一定是 token / sessionId;Session 中的 token / sessionId 也不需要非得通过 Cookie / Set-Cookie 传递 ~~

在这里插入图片描述

四、核心方法

在 Servlet 中也专门提供了相关的API,让我们来操作 Cookie 和 Session。

4.1 HttpServletRequest 类中的相关方法

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

4.2 HttpServletResponse 类中的相关方法

方法描述
void addCookie(Cookie cookie)把指定的 cookie 添加到响应中

4.3 HttpSession 类中的相关方法

一个 HttpSession 对象里面包含多个键值对,我们可以往 HttpSession 中存任何我们需要的信息!

方法描述
Object getAttribute(String name)该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null
void setAttribute(String name, Object value)该方法使用指定的名称绑定一个对象到该 session 会话
boolean isNew()判定当前是否是新创建出的会话

4.4 Cookie 类中的相关方法

每个 Cookie 对象就是一个键值对。

方法描述
String getName()该方法返回 cookie 的名称。名称在创建后不能改变 (这个值是 Set-Cookie 字段设置给浏览器的)
String getValue()该方法获取与 cookie 关联的值
void setValue(String newValue)该方法设置与 cookie 关联的值
  • HTTP 的 Cookei 字段中存储的实际上是多组键值对,每个键值对在 Servlet 中都对应了一个 Cookie 对象
  • 通过 HttpServletRequest.getCookies() 获取到请求中的一系列 Cookie 键值对
  • 通过 HttpServletResponse.addCookie() 可以向响应中添加新的 Cookie 键值对

五、代码示例: 实现用户登陆

实现简单的用户登陆逻辑。

5.1 需求

1)登陆页面。用户可以填写用户名 + 密码 (login.html)
2)Servlet 来处理登陆请求。(LoginServlet.java)
3)使用另一个 Servlet 来生成主页内容 (登陆成功后,跳转到的页面) (IndexServlet)

5.2 登录页面的实现

login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登陆</title>
</head>
<body>
    <!-- 提交的数据交给 LoginServlet 来处理的 -->
    <form action="login" method="post">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="submit" value="登陆">
    </form>
</body>
</html>

LoginServlet.java:

package login;

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;

// 使用这个类来处理登陆请求
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 从请求中获取到页面提交的用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        // 2. 验证用户名密码是否正确
        //    正常这个操作要查数据库. 此处为了简单, 直接写成硬编码了. (把正确的用户名和密码写死了)
        //    假定正确的密码是 zhangsan 123
        if ("zhangsan".equals(username) && "123".equals(password)) {
            // 登陆成功
            // a) 创建一个会话. 用户刚登陆成功, 之前是没有会话的. 重新分配个新的会话给用户.
            // getSession
            //    * 创建 sessionId 和一个 HttpSession 对象
            //    * 把这两个内容以键值对的形式插入到内存的 哈希表 里
            //    * 把 sessionId 通过 Set-Cookie 写到响应中.
            HttpSession session = req.getSession(true);
            // 随意的设置 "键值对" 了. (HttpSession 对象自身也相当于是一个 哈希表)
            session.setAttribute("username", "zhangsan");
            // b) 让响应重定向到 "主页"
            resp.sendRedirect("index");
        } else {
            // 登陆失败
            resp.setStatus(403);
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("登陆失败, 用户名或者密码错误");
        }
    }
}
  • 此处的 getSession 参数为 true,表示查找不到 HttpSession 时会创建新的 HttpSession 对象,并生成一个 sessionId,以键值对的形式插入到 哈希表 中,并且把 sessionId 通过 Set-Cookie 返回给浏览器。

在这里插入图片描述

通过 http://127.0.0.1:8080/yyhjava/login.html 访问页面:

在这里插入图片描述
登录"zhangsan","123"后跳转页面:

在这里插入图片描述

此时还并没有实现跳转页面,所以就是 404 ~~

Cookie 和 Session 细节:

1)在登录页面的响应中,有这样一行:

在这里插入图片描述

这就是通过 getSession 操作创建会话的同时,生成 sessionld 并且把这个 sessionld 通过 Set-Cookie 返回给浏览器了!!!

2)在页面跳转的请求中,有这样一行:
在这里插入图片描述

这就是刚才设置的 sessionld 啊 ~ 说明已经保存在浏览器中 (本地)了!

当然也可以在浏览器查看:(点击 URL 前的小图标 ~)

在这里插入图片描述

是不是很眼熟?当然一模一样 ~

5.3 跳转页面的实现

package login;

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;

// 登陆成功后, 跳转到的主页
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 首页中也先获取 session, 此处的 session 正是刚才登陆页的时候, 登陆成功的逻辑中创建出来的.
        // 此处 参数 写作 false 即可. 表示不新建. 如果不存在, 就返回 null 就是了.
        HttpSession session = req.getSession(false);
        if (session == null) {
            resp.setStatus(403);
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("您尚未登录, 不能访问主页!");
            return;
        }

        String username = (String) session.getAttribute("username");

        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write("欢迎来到主页! " + username);
    }
}
  • 在这个代码中是看不到 “哈希表”,也看不到 sessionId 这样的概念的。getSession 操作内部提取到请求中的 Cookie 里的 sessionId,然后查找哈希表,获取到对应的 HttpSession 对象。
  • getSession 参数为 false,则获取不到 HttpSession 对象,不会创建新的 HttpSession,而是返回 null。此时说明用户没有登陆。

在这里插入图片描述

此时就可以成功实现逻辑了!!!登录后:
在这里插入图片描述

举报

相关推荐

0 条评论