• 实现登陆模块时Cookie,Session,Token的理解


    引言

    先思考问题:
    1、如何实现登陆?

    (1)表单输入账号密码
    (2)后台数据库验证

    2、为什么平日登陆一次,隔几天打开浏览器进入网页,登录状态还在呢?

    因为保存了用户的登陆状态。下次访问的时候,先查看是否保存登录状态,有则不需要重新登陆。

    登录状态的处理:Cookie,Session,Token三种方式
    接下来看看如何区分和实践

    一、简化版登陆(不保存登录状态)

    这样的方式,第一次打开浏览器访问网页:需要登录。然后关闭浏览器
    第二次打卡浏览器访问网页:需要重新登陆

    在这里插入图片描述

    二、Session 登陆

    功能期望:

    • 先直接访问A界面,会跳转到登陆
    • 登陆完毕后,可以访问A界面
    • 然后可直接访问B界面,不需要登陆

    在这里插入图片描述
    先了解一个概念:
    用甲的账号密码登录成功后,服务器会自动创建一个Session对象 ,表明甲登陆过了
    用乙的账号密码登录成功后,服务器也会自动创建一个Session对象 ,表明乙登陆过了
    那怎么区分已经创建的Session对象,用唯一标识Session id区分
    Session Id = 1111 就是 甲的Session对象

    账号登陆成功后服务器会创建这样一个散列表保存登陆状态,这个表存在服务器的内存中

    在这里插入图片描述
    看一下我们如何利用Session实现登录一次,多次访问
    可以看到,第二次访问的时候我们仅需要在访问路径上带上标识甲的Session id
    ”localhost:8080/B?SessionId = 1111“ 就可以匹配服务器内存中的Session id
    在这里插入图片描述
    那么每次都需要在请求路径上手写Session id,简直太麻烦了,有什么办法可以自动在发送请求路径的时候,顺便发送Session Id呢?
    在这里插入图片描述
    Cookie就可以实现这个功能

    三、Cookie+Session 实现登录

    甲登陆成功后,服务器为甲创建 Session Id + Session 对象
    然后服务器创建Cookie对象,并把Session Id存入Cookie对象
    最后返回给浏览器,保存在浏览器的内存里

    第二次访问时候,保存在浏览器内存里的Session Id会自动的 与 访问路径一起发送给服务器
    在这里插入图片描述
    大部分时候我们不仅仅在Cookie中保存Session Id,还保存一些其他的信息,以此来说明这是用户甲发起的请求,因此千万不可以被别人知道了我们的Cookie
    CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

    有人就疑惑了,是不是必须在cookie中设置账号密码呢?
    如果我们修改了账号密码,且只携带Session Id,那岂不是当Session Id通过时,就可以不用登陆,那密码不白改了。
    所以我们需要携带账号密码,先验证Seesion Id是否一致,再验证账号密码是否一致,这样

    在这里插入图片描述
    这里有个实例:
    可以看到服务器返回给浏览器的cookie,包含了JsessionId,name和pwd
    在这里插入图片描述

    从后端代码编写的角度

    传入账号密码登陆成功后,后端在跳转界面之前,需要实现两步骤
    
          1.  因为登录成功了,创建一个Session对象(根据此Session对象可以识别不同的用户)
    此Session对象保存在服务器内存中
    
          2.  服务器会继续创建一个Cookie对象,将Session传给Cookie,然后把Cookie返回给浏览器
    浏览器会把Cookie保存在浏览器内存中,如下图
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    第一次访问:先登陆,并且保存登录状态
    在这里插入图片描述

    第二次访问:利用登录状态
    在这里插入图片描述

    AServlet:
    连接数据库,查看匹配信息
    if(success){
    	1 Tomcat服务器自动创建session对象
    	2 request.getSession() //获取session对象
    	3 将session对象放入Session域中
    		//设置Cookie
    		Cookie cookie = new Cookie(设置Name属性,设置Value属性) 
    		cookie.setMaxAge(时间)
    		cookie.path(路径)
    		response.addCookie(cookie)  //将服务器生成的cookie返回给浏览器保存起来
    	4 跳转到A.jsp界面
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    BServlet1 request.getsession(false) //禁止服务器在B中自动创建session对象
    2 获取Session对象
    if(session不为空 && session.getAttribute(对象)不为空){
    	获取浏览器的cookies
    	3 进入B界面
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Session Id保存在服务器的内存中,所以服务器的压力就会很大。有没有什么办法可以减轻服务器的压力呢?这个时候需要Token了

    四、Token登陆

    Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

    使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。

    这意思是不是和Cookie+Session类似,画个图分析一下
    在这里插入图片描述
    可以看到我们不再需要在服务器存储Session Id,极大地降低服务器的压力。

    先看看第一次登陆成功后,服务器如何产生的Token
    第一步:

    在这里插入图片描述
    第二步:
    在这里插入图片描述
    第三步:
    在这里插入图片描述

    这样就得到了返回浏览器的Token

    再来看看怎么生成新的Token进行验证

    在这里插入图片描述

    如果善于观察会发现,这个Token也是可以被人截获的,只需要用Baes64解析,至少可以得到两个密文,而这两个密文就是我们的数据信息,如果里面有账号密码也是有泄露的风险。

    拓展:
    再思考一个问题:
    既然Token是由 Header,Playloder,签名 三部分决定的。那这里面都存储一些什么信息区分不同的客户端。(也就是说,A,B浏览器向服务器发送Token,服务器是怎么区分的)

    为了互联网的规范性,我们对这三部分应该存储什么信息有一个规范:JSON WEB TOKEN(简称JWT)意思只要你想要使用Token,可以考虑参考这个标准。
    JWT规定:

    第一部分(Header存放:声明类型typ,加密算法alg)
    {
      'typ': 'JWT',
      'alg': 'HS256'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后用Base64加密生成密文,这也是我们为何解密 Header密文 就可以知道 加密算法HS256

    第二部分(Playloder存放:
    
    标准中注册的声明: 包括
    	iss: jwt签发者
    	sub: jwt所面向的用户
    	aud: 接收jwt的一方
    	exp: jwt的过期时间,这个过期时间必须要大于签发时间
    	nbf: 定义在什么时间之前,该jwt都是不可用的.
    	iat: jwt的签发时间
    	jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
    	
    公共的声明:
    	自定义的一些内容:name:"王冰冰"
    	
    私有的声明:
    	虽然叫私有,但也不安全,不推荐放敏感信息
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    截取Token主要针对这一部分内容。

    第三部分:叫做signature,为生成签名

    signature组成:Header密文.Playloder密文.secret
    
    • 1

    在这里插入图片描述
    这里可以看看前面介绍如何利用服务器的密钥生成签名,对比一下。
    其实这个secret是一个私钥,存放在服务器中,也就是前面说的服务器密钥。

    在这里插入图片描述

  • 相关阅读:
    1626C - Monsters And Spells ,D - Carry Bit 组合数学
    【算法】字典序
    2023-09-09青少年软件编程(C语言)等级考试试卷(二级)解析
    Matlab论文插图绘制模板第125期—特征渲染的三维气泡图
    39个你需要知道的Git命令
    SpringCloud第九章:Config 分布式配置中心
    delete the swap file “.houseupdate.sh.swp“
    HashMap 源码解读(JDK1.8)
    MYSQL数据库-库/表操作
    【Leetcode】383. 赎金信
  • 原文地址:https://blog.csdn.net/heng000000/article/details/127901019