实现登陆模块时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保存在浏览器内存中,如下图

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

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

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界面
}
BServlet1 request.getsession(false) //禁止服务器在B中自动创建session对象
2 获取Session对象
if(session不为空 && session.getAttribute(对象)不为空){
	获取浏览器的cookies
	3 进入B界面
}

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'
}

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

第二部分(Playloder存放:

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

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

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

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

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

在这里插入图片描述

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
登录模块实现可以采用多种方法,以下是一些常见的实现方法: 1. 基于Session的身份验证:用户在登录,服务器会创建一个Session并将Session ID存储在客户端的Cookie中。在用户每次请求,服务器会验证Session ID是否有效,从而判断用户是否登录。如果Session ID有效,则认为用户已经登录,否则认为用户未登录。 2. 基于Token的身份验证:用户在登录,服务器会生成一个Token并将Token存储在客户端的Cookie中。在用户每次请求,客户端会将Token发送到服务器进行验证。如果Token有效,则认为用户已经登录,否则认为用户未登录。 3. 基于OAuth2.0的身份验证:OAuth2.0是一种授权框架,可以用于实现用户身份验证。用户在登录,会被重定向到授权服务器进行身份验证,授权服务器会返回一个Access Token。客户端在每次请求,需要携带Access Token进行验证。如果Access Token有效,则认为用户已经登录,否则认为用户未登录。 4. 基于OpenID Connect的身份验证:OpenID Connect是一种基于OAuth2.0的身份验证协议,它提供了更加安全和灵活的身份验证方式。用户在登录,会被重定向到认证服务器进行身份验证,认证服务器会返回一个ID Token。客户端在每次请求,需要携带ID Token进行验证。如果ID Token有效,则认为用户已经登录,否则认为用户未登录。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值