cookie VS session

1.前言

会话的定义:我们这里是指某个web系统的会话,指用户登录以后,在退出之前,都是一个会话。
退出一个会话的条件:注销或者超过系统设置的会话时间。

用户信息(session和cookie的使用前景):因为http是一个无状态协议,就是说这一次的请求和上一次的请求是没有任何关系的,互不认识互不关联。这种状态的好处是快速,坏处是在需要进行用户状态保持的场景时(比如。登录状态下进行页面的跳转,用户信息多页面共享,我们常用的记住密码等),需要用一些手段来保持信息。这个手段就是cookie(网络饼干)和session。

2.cookie:

因为http是一个无状态的协议,但是访问有些资源的时候我们需要经过认证用户才能够访问,而且要一直保持在线状态,所以我们就用cookie。cookie是一种在浏览器解决的方案,将登陆认证之后的用户信息保存在本地的浏览器中,后面每次发起http请求时,都会自动携带该信息,就能够达到认证用户,保持用户在线的作用;
cookie原理客户端本地保存用户身份信息,之后的每次请求中就可以携带这些信息了。
使用场景:登录界面 免登录/记住密码/10天免登录等,从本地获取用户信息。
**默认:**本地Cookie保存信息,每次请求的时候,都会在请求头中携带发送,格式为:Cookie:k1 = v1&k2 = v2…
Cookie是区分域名的,不同域名,保存在不同路径下
在这里插入图片描述
在这里插入图片描述

3. session:

将用户敏感信息放到本地浏览器中,是能够解决一定的问题,但是又会引发安全性的问题。因为如果cookie丢失,就会造成密码泄露等问题。所以我们采用session,将用户敏感信息保存在web服务器中,web服务器会通过md5算法,会生成唯一的值(session id也就是下图中的V),将该id保存在客户端中。随后客户端后续请求,浏览器都会自动的携带该id,进而再进行服务端认证,从而达到保持登录的状态。

session的作用:用户登录时,服务端保存用户身份信息(map<v , session>,因为session内部也是一个map所以也可以认为是map<k,map<k,v>>)。在之后访问敏感资源时,通过请求k=v(映射关系),服务端通过k获取v,在map中获取用户身份信息(session)。

k是固定的,v是随机生成的。

  • 一个用户,一个会话里面,k与V的值都是固定的。
  • 对于K:不同的用户,或者是同一个用户的不同会话,k都是固定的。
  • 对于V:同一个用户,同一个会话中是一样的。下一个会话就会重新再生成V,然后映射给K。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

通过session,解决了访问敏感资源携带用户信息不安全性的问题。

4. session和cookie的关系

通过上面的图解可以看出来,要使用session,其实还是需要使用cookie机制来保存session ID。

如果万一在客户端cookie机制被禁止了,那么session就无法使用了??我们可以用代替的方法

  1. 很多的Web服务器Session的默认实现方式都是采取Cookie实现的。——如果不是cookie的方式,那么客户端就要写代码请求包装/响应解析数据。(Cookie机制里面默认包含此项)
  2. 经常被使用的技术叫做URL重写,就是把session id 直接附加到URL的路径的后面。
  3. 还有一种技术就是 表单隐藏字段,就是服务器会自动修改表单,添加一个隐藏字段,以使在表单提交的时候能够把session id 传递回服务器。

所以保持登录的关键不是cookie,而是通过cookie保存和传输的session ID,本质是能够获取用户信息的数据。

5.session和cookie的区别(面试题)

cookie是web服务器发送给浏览器的一块信息,浏览器会在本地的一个文件中给每个web服务器都存储一个cookie。以后浏览器再给特定的web服务器发送请求时,同时会发送所有为该服务器存储的cookie。
session是存储在web服务器端的一块信息。session对象存储特定用户会话所需要的属性以及配置信息。当用户在应用程序的web页之间跳转时,存储在session对象中的变量不会丢失,而是在整个会话中一直存在下去。

区别:

  • cookie以文本格式存储在本地浏览器中,而session存储在web服务端。
  • 因为每次都要发送http请求,都要携带有效的cookie信息,所以cookie的大小一般都限制在4k以内,防止增加网络压力。
  • 可以轻松访问cookie值但是我们无法轻松访问会话值,因此session方案更加安全。
  • 无论客户端做怎样的设置,session都能后正常工作,而当客户端禁止cookie时,将无法使用cookie。
  • 在存储数据量方面:session能够存储任意java对象,cookie只能存储string类型的对象。

6.代码练习

LoginServlet模拟校验session:

package bmiaoservlet;
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;

//servlet提供路径
/**
 * 通过http请求路径/Login路径映射到本servlet,
 * 通过@WebServlet中配置路径关联
 * @WebServlet必须以/开头
 */
@WebServlet("/login")//关联login.html
public class LoginServlet extends HttpServlet {
    @Override//重写
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //编写请求编码,UTF-8编码
        req.setCharacterEncoding("UTF-8");//请求数据编码,请求体产生
        resp.setCharacterEncoding("UTF-8");//服务端响应的内容设置编码
        //告诉浏览器:1,你的数据类型(浏览器处理数据的方式)
        //2.编码(浏览器解析数据的编码)
        resp.setContentType("text/html; charset = UTF-8");
        //getParameter获取url中或者请求体中的数据,根据key获取value,获取不到则为null
        //接收的请求数据类型,可以是表单提交:application/x-www-form-urlencoded


        //查询用户名和密码是否正确
        String username = req.getParameter("username");//根据key获取value,获取不到则为null
        String password = req.getParameter("password");
        PrintWriter pw = resp.getWriter();
        //模拟校验session
        // 如果用户名和密码设置无误
        if ("abc".equals(username)&& "123".equals(password)){
            //getSession()这个方法:
            //获取当前http请求的Session。
            // 如果获取不到,参数为true时,创建一个
            // 如果为false,那就返回null

            //一般的使用,登录并且用户身份校验通过,getSession(),然后存放用户信息进去;
            //           访问敏感资源的时候,getSession(false),然后判断是否为null,如果为null就肯定没登录
            //           还可以通过存放的用户信息,校验访问权限
           // HttpSession session =  req.getSession(false);
            //整体看服务端保存session的结构为map<V,map<K,V>>,因为session也是一个map结构
            HttpSession session =  req.getSession();//=getSession(true)
            session.setAttribute("user",username);
            //用转发或重定向(推荐转发)可以跳转到index.html
            resp.sendRedirect("index.html");
        }
        else {
            pw.print("登录失败");
        }
        pw.flush();
    }
}

TestServlet模拟敏感资源校验

package bmiaoservlet;

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("/test")
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //编写请求编码,UTF-8编码
        req.setCharacterEncoding("UTF-8");//请求数据编码,请求体产生
        resp.setCharacterEncoding("UTF-8");//服务端响应的内容设置编码
        //告诉浏览器:1,你的数据类型(浏览器处理数据的方式)
        //2.编码(浏览器解析数据的编码)
        resp.setContentType("text/html; charset = UTF-8");
        //getParameter获取url中或者请求体中的数据,根据key获取value,获取不到则为null
        //接收的请求数据类型,可以是表单提交:application/x-www-form-urlencoded
        PrintWriter pw = resp.getWriter();

        //类似于loginServelt代码
        /**敏感资源需要校验
         * 1.用户是否登录,没有登录,就跳转到登录页面(响应401状态码)Unauthorized(未被授权的)
         * 2.校验用户权权限,是否有访问当前资源权限(响应403状态码)Forbidden(禁止访问的)
         **/
        HttpSession session = req.getSession(false);
        if (session == null){//对应1用户没有登录的情况

            resp.setStatus(401);//校验用户是否登录
            pw.println("用户没有登录,不允许访问");
            pw.flush();//下面的逻辑是登录成功后执行的,此处不涉及,所以刷新一下直接返回
            return;
        }
        String username =  (String)session.getAttribute("user");//之前设置的,需要强转为字符串类型
        //真实情况中会保存用户很多信息,这里只模拟保存用户名
        //伪代码
        /**if(!user对象.获取权限.检验是否包含当前的请求资源){
            //对应用户已经登录但是没有访问权限,则相应403
            resp.setStatus(403);//没有访问权限
            pw.println("用户没有访问权限,禁止访问");
            pw.flush();
            return;
        }
         **/

        //测试用,演示http请求头,响应头,状态码
        //演示400,301/302/307重定向,转发
        //模拟方式:请求heep://localhost:8080/项目部署名/test?i=
        String i= req.getParameter("i");
        if ("1".equals(i)){//重定向(考点)

          resp.sendRedirect("index.html");
        }
        else if ("2".equals(i)){//转发
      req.getRequestDispatcher("index.html").forward(req,resp);
        }else {//如果是int,就正常返回,如果不是,就返回400
            try {
                Integer.parseInt(i);
                //能够解析为int ,就正常返回
                pw.println("正确的数值" +i);

            } catch (NumberFormatException e) {
                //非int型则返回400
                resp.setStatus(400);
                pw.println("非数值"+i);
            }

        }

        pw.flush();
    }
}

经测试后,可以看到,浏览器此时已经携带session id了,后续的访问就可以携带这个id了
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值