Servlet_Cookie Session详解

HTTP协议是一种无状态的协议
怎么理解无状态:认证的请求-响应 无法和 业务请求-响应 相对应
每次的的 请求-响应都是独立的
所以引入了Cookie

一、Cookie

狭义的讲就是:在认证阶段,返回给用户的可验证证明在这里插入图片描述
通过这个过程,就可以使得HTTP协议具有状态了在这里插入图片描述
上图是a和b分别认证并保存各自Cookie信息的过程,当a和b二次请求的时候,就带着各自的Cookie
通过读取Cookie就能知道新的请求是由谁发起的,解决了HTTP无状态特性

Cookie是由响应格式返回的:

  • 响应:状态行+响应头+响应体
    状态行:HTTP版本以及成功与否
    响应头 —— 一般是给浏览器看的
    响应体:正文部分,也就是用户想要的资源 —— 用户可以看到的

Cookie其实是放在了响应头里,通过 Set-Cookie:key = value 这个响应头形式

同样的:再次请求
请求也是由请求行+请求头+请求体组成的
请求时带着的Cookie也是在请求头里,是哪个请求头呢? Cookie: key = value

1、先通过手动方式设置Cookie(已经提前配置好了该Servlet项目)

在这里插入图片描述
CookieDemo.java

package tomato;

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 java.io.IOException;

@WebServlet("/set-cookie")
public class CookieDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //手动设置响应头 resp.setHeader
        resp.setHeader("Set-Cookie","name = Tomato");
    }
}

Printcookie.java

package tomato;

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

@WebServlet("/print-cookie")
public class PrintCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/plain;charset=utf-8");
        PrintWriter writer = resp.getWriter();

        //手动从请求头中获取
        String cookie = req.getHeader("Cookie");
        if (cookie == null){
            System.out.println("没有设置Cookie!");//这是打印在终端的
            writer.println("没有设置Cookie");//打印在客户端的
        }else{
            System.out.println(cookie);
            writer.println(cookie);
        }
    }
}

运行后结果:(注意url,是直接访问的print-cookie)
浏览器:
在这里插入图片描述

终端:
在这里插入图片描述

然后我们什么都不变,在浏览器调用一下 set-cookie:
在这里插入图片描述

然后回到刚刚的print-cookie页面刷新:
此时可以看到拿到了cookie
在这里插入图片描述
在这里插入图片描述
cookie信息保存后,当我们再次请求时,就可以直接拿着cookie认证了

总结
  1. 狭义cookie:身份证明
  2. 如何传递:
    1)服务器设置cookie时(有时候也叫种cookie),通过Response Header : Set-Cookie : k = v
    2)客户端带着Cookie时,通过Request Header : Cookie : k = v
注意:每次当我们的代码有变化的时候,都需要重启Tomcat或者重新部署

2、通过Cookie对象设置Cookie信息

就把Cookie看作是一份证明,其中包含
1、 有效内容: key = value
2、 适用范围:哪些Host中可以使用
3、 过期时间
4 、 其他属性
Cookie:k=v;domain=适用范围;expire=2020-04-17

实际上Sevlet将他封装成了Cookie对象

CookieDemo.java

package tomato;

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

@WebServlet("/set-cookie")
public class CookieDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过Cookie对象设置Cookie信息
        Cookie cookie = new Cookie("name","tomato");
        resp.addCookie(cookie);
        //设置过期时间
        cookie.setMaxAge(10*60);//600s后过期
    }
}

效果和1中的手动设置Cookie是一样的
在这里插入图片描述
print-cookie.java

@WebServlet("/print-cookie")
public class PrintCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/plain;charset=utf-8");
        PrintWriter writer = resp.getWriter();

		//当然也可以打印过期时间等等
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies){
            System.out.println(cookie.getName() + "=" + cookie.getValue());
            writer.println(cookie.getName() + "=" + cookie.getValue());
        }
    }
}

运行结果:
在这里插入图片描述

二、Session

光用cookie有什么问题吗?
当前的cookie中,所有的信息全部来自客户端,也就是完全信任客户端,客户端说它是谁,服务器就认为他是谁,实际上这个身份认证是没有证明的,缺少第三方的辅助,所以就引入了Session

Cookie + Session 配合工作

得到用户数据,认证后,将对象放在Session服务器中,然后返回给HTTP服务器的是Session-ID,HTTP服务器返回给客户端的是带着该Session-ID的Set-Cookie:Session-ID = ?,浏览器会保存该信息,当下一次用户发起请求的时候,会从Cookie中取出该Seesio-ID,然后去session服务器中取资源
在这里插入图片描述
Cookie + Session 配合使用,“安全的” 解决了HTTP的无状态问题

User.java

//用户对象
package tomato;

import java.util.ArrayList;
import java.util.List;

public class User {
    String username;
    String password;

    private static List<User> userList = new ArrayList<>();

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    static {
        userList.add(new User("a1","a"));
        userList.add(new User("b2","bb"));
        userList.add(new User("c3","ccc"));
    }

    //登录
    public static User login(String username,String password){
        for (User user: userList){
            if (user.username.equals(username) && user.password.equals(password)){
                return user;
            }
        }
        return null;
    }
}

 

LoginServlet.java

//验证登录
package tomato;

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;
import java.io.PrintWriter;

@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");

        //得到Session信息
        HttpSession session = req.getSession();
        resp.setContentType("text/plain; charset=utf-8");
        PrintWriter writer = resp.getWriter();

        User user = User.login(username,password);
        if (user != null){
            //表示登陆成功,把User对象放进Session服务器里
            session.setAttribute("user",user);
            writer.println("登录成功,欢迎" + user.username);
        }else{
            writer.println("没有这个用户");
        }
    }
}

WhoAmI.java

//查看当前用户
package tomato;

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;
import java.io.PrintWriter;

@WebServlet("/who-am-i")
public class WhoAmI extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/plain; charset=utf-8");
        PrintWriter writer = resp.getWriter();
        HttpSession session = req.getSession();
        User user = (User)session.getAttribute("user");

        if (user == null) {
            writer.println("我不知道你是谁");
        }else {
            writer.println("你是:" + user.username);
        }
    }
}

login.html

//简单登录页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/login" method="post">
    <input type="text" name="username">
    <input type="text" name="password">
    <button type="submit">登录</button>
</form>
</body>
</html>

直接访问who-am-i:
在这里插入图片描述

登录:
在这里插入图片描述
在这里插入图片描述
这个时候再访问who-am-i:
在这里插入图片描述
在这里插入图片描述

结果解释:
在这里插入图片描述

在这里插入图片描述

Cookie和Session区别?

其实这个问题本身就有点问题,cookie和session是配合工作的,而不是两种方案的选择

硬要说的话:

  1. Cookie + Session一起“安全地”解决HTTP无状态的问题
  2. Cookie是主要用于 客户端和HTTP服务器之间,保持会话
    Cookie主要保存在客户端的电脑上(浏览器的内存、文件中)
  3. Session主要是服务器内部使用,目的是解决Cookie本身不太安全的问题(恶意用户,泄露篡改信息)
  4. Session一半保存在服务器电脑上(内存、文件、MySQL、专门的Session服务器)
  5. 在HTTP协议传输时,有两个Header:
    1)Cookie——请求头:
    2)Set-Cookie——响应头
  6. Cookie有适用范围(与主机——Host有关)
  7. 有过期时间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值