Cookie 和 Session

更新时间:2022-05-16 17:15:49点击次数:910次
1. 什么是 Cookie
因为HTTP是无状态的协议,无法根据之前的状态进行本次的请求处理
为了保留无状态协议这个特征,于是引入了 Cookie 信息来控制客户端的状态.
Cookie会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie.当下次再给该服务器发送请求的时候,客户端会自动在请求报文中加入Cookie值后发送出去.

服务器端发现客户端发送来的 Cookie 后,会去检查是哪一个客户端发来的连接请求,对比服务器上的记录,最后得到之前的状态信息.

在这里插入图片描述

此时在服务器这边就需要记录Cookie信息, 这个就是 Session 机制所做的工作
2. 什么是 Session

Session 译为 会话 .Session是存储在服务端的,当客户端第一次访问服务端的时候,服务端会把客户端的信息存储在服务器上,当客户端再次访问的时候,就可以通过 Session中查找该客户端的状态就可以了.存储的方式类似于 哈希表.

在这里插入图片描述

3. Cookie 和 Session 的区别
Cookie 是保存在 客户端, Session 是保存在 服务端
Cookie 不安全
单个Cookie保存的数据不能超过 4k
Cookie 和 Session 经常会在一起配合使用. 但是不是必须配合
4. 相关方法
HttpServletRequest 类中的相关方法
方法 描述
HttpSession getSession() 在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null
Cookie[] getCookies() 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对.
HttpServletResponse 类中的相关方法
方法 描述
void addCookie(Cookie cookie) 把指定的 cookie 添加到响应中.
HttpSession 类中的相关方法
方法 描述
Object getAttribute(String name) 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null.
void setAttribute(String name, Object value) 该方法使用指定的名称绑定一个对象到该 session 会话
boolean isNew() 判定当前是否是新创建出的会话
Cookie 类中的相关方法
方法 描述
String getName() 该方法返回 cookie 的名称。名称在创建后不能改变。(这个值是 SetCooke 字段设置给浏览器的)
String getValue() 该方法获取与 cookie 关联的值
void setValue(String newValue) 该方法设置与 cookie 关联的值。
注意事项
通过 HttpServletRequest.getCookies() 获取到请求中的一系列 Cookie 键值对.需要带有参数
当为 true 的时候, 如果 session 不存在,就会创建,如果存在,就获取session然后返回
当为 false 的时候,如果 session 不存在,就会返回null,如果存在,就获取session然后返回
HTTP 的 Cooke 字段中存储的实际上是多组键值对. 每个键值对在 Servlet 中都对应了一个 Cookie对象.Cookie里主要有 key 和 value 两个属性
5. 实现一个用户登录
① 创建 maven 项目,引入需要的库和目录
创建 webapp/WEB-INF/web.xml
web.xml
<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
</web-app>
引入 Servlet
② 首先设计好前端后端交互接口
客户端给服务器第一次交互, 登录请求
登录账号,之后重定向到第二次交互
此时重定向到第二次交互,访问主页
③ 写 login.html (登录页面)
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>Document</title>
  <link rel="stylesheet" href="css/common.css">
  <link rel="stylesheet" href="css/login.css">
</head>
<body>
    <div id="leader">
      <div class="login">
        <form action="login" method="POST">
          <div class="title">某某管理系统</div>
          <div class="one"><input type="text" name="username" class="user"><input type="password" name="password" class="password"></div>
          <div class="submit"><button>登 录</button></div>
        </form>
      </div>
    </div>
</body>
</html>
common.css
* {
    padding: 0;
    margin: 0;
}
html,body {
    width: 100%;
    height: 100%;
}

login.css
#leader{
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}
.login {
    background-color: pink;
    width: 400px;
    height: 290px;
    padding: 25px;
    border-radius: 10px;
}
.login .title{
    font-size: 30px;
    font-weight: 600;
    text-align: center;
    margin: 5px;
}
.login .one{
    display: flex;
    flex-direction: column;
    align-items: center;
}
.login .user,.login .password {
    width: 380px;
    height: 35px;
    margin: 10px;
    border-radius: 8px;
    padding: 5px;
    border: none;
}
.login .submit{
    margin: 10px;
}
.login .submit button{
    display: block;
    margin: 0 auto;
    width: 100px;
    height: 50px;
    background-color: orange;
    color: white;
    border-radius: 5px;
    border: 0;
}
.login .submit button:active{
    background-color: red;
}
④ 写 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;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        // 1. 先从请求的body中读取 用户名 和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 2. 判定 用户名密码 是否正确(这里直接固定)
        if(!"wz".equals(username) || !"123456".equals(password)){
            // 用户名和密码有错误的
            resp.getWriter().write("登录失败!");
            return;
        }
        // 3. 登录成功,则创建一个会话出来.
        HttpSession httpSession = req.getSession(true);
        httpSession.setAttribute("username","wz");
        httpSession.setAttribute("loginCount",0);
        // 4. 让页面跳转到主页,使用重定向
        resp.sendRedirect("index");
    }
}
⑤ 写 IndexServlet
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 {
        // 根据当前用户请求中的 sessionId, 获取到用户信息,并显示到页面上
        resp.setContentType("text/html;charset=utf-8");
        // 1. 判定当前用户是否已经登录了.
        HttpSession httpSession = req.getSession(false);//这里如果不存在就不需要创建.
        if(httpSession == null){
            resp.sendRedirect("login.html");
            return;
        }
        // 2. 如果已经登录,就可以从 HttpSession 中拿到用户信息了
        String username = (String) (httpSession.getAttribute("username"));
        Integer loginCount =  (Integer) (httpSession.getAttribute("loginCount"));
        loginCount = loginCount + 1;
        httpSession.setAttribute("loginCount",loginCount);
        // 3. 返回一个 HTML 页面
        StringBuilder html = new StringBuilder();
        html.append("<div>用户: "+username+"</div>");
        html.append("<div>访问次数: "+loginCount+"</div>");
        resp.getWriter().write(html.toString());
    }
}
运行结果
首先浏览器输入 http://127.0.0.1:8080/ForLogin/login.html
输入 "wz" "123456"
在刷新页面的时候,会增加访问次数
查看抓包结果

第一次交互的请求

在这里插入图片描述

第一次交互的响应
第二次交互的请求
第二次交互的响应

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息