Session身份验证和JW身份验证 | 青训营笔记

279 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

来源

一、Session 认证机制

HTTP是无状态协议

HTTP无状态是指?

  HTTP协议对事务处理是没有记忆能力,也就是说服务器不知道客户端是什么状态。

这是什么意思呢?

  当我们向服务器发送请求后,服务器解析处理请求,然后返回响应,服务器负责完成这个过程(也是一个事务),而这个过程是独立的,服务器不会记录前后状态的变化,也就是缺少状态记录。

无状态导致的后果?

  意味着后续发出的请求需要处理前面请求的响应,则必须重传,这也导致需要额外传递一些前面的重复请求,才能获取后续响应。但为了保持前后状态,我们也不能将前面的请求全部重传一次,这太浪费资源了;就好像如果一个网站每次发出一个请求前都要先发出一次登录请求,这无疑大大增加了资源浪费程度。

什么是Cookie ?

Cookie是存储在用户浏览器中的一段不超过4 KB的字符串。它由一个名称(Name)、一个值(Value) 和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。

不同域名下的Cookie各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie 一同发送到服务器。

一些常见的cookie

5e3aef782c37defea155607af23d489.jpg

Cookie在身份认证中的作用

客户端第一次请求服务器的时候,服务器通过响应头的形式,向客户端发送一个身份认证的 Cookie,客户端会自动将Cookie保存在浏览器中。

随后,当客户端浏览器每次请求服务器的时候,浏览器会自动将身份认证相关的Cookie,通过请求头的形式发送给服务器,服务器即可验明客户端的身份。

现在我们知道了cookie在前后端交互的意义了,但是cookie其实十分不安全,由于cookie容易被获取,所以我们一下重要信息显然不能简单的用cookie来存储。这时我们就需要cookie + 身份验证的方法诞生了——session。

Session的工作原理

在登陆注册时,客户端会先将密码和账号发给服务端server,sever会验证密码和账号,并返回一个session_id给client,并且server也会把这个session_id存在数据库中,当client再次发送请求时,会携带该域名下的所有cookie给server,如果其中有用户的信息的session_id,server会拿取这个session_id到数据库查找对应的用户名和密码,如果与client的用户名密码一致,server才能验证成功身份返回对应的内容。

注意:session_id一般存储在cookie中,但是由于JS不让访问这种cookie,因此对于跨域的请求就无法完成了。

SameSite属性

SameSite可以限制第三方cookie的使用。SameSite可以设置为三个属性strict,Lax,None,接下来我们将从三个属性分别去介绍。

属性一:strict属性:该属性表示表示完全禁止第三方cookie,也就是在跨站时,均不会携带cookie,只有当前站点的url和访问的站点的url一致时,才能携带cookie。但是我们此时想一种情况,比如说当前站点A存在一个链接,链接到gitte网站,如果我们之前已经登录了gitte网站的话,则我们再次访问该网站时应该是处于登录状态的。但是我们对当前站点cookie设置了SameSite属性为strict值,所以当前跳转链接并不会携带cookie,所以我们的信息无法得到认证,此时就需要重新登录。

Set-Cookie: CookieName=CookieValue SameSite=strict

属性二:Lax:该属性比strict的属性要宽松一些,其允许我们在跨站使用get请求时携带cookie。导航到目标网址的get请求主要包括三种,链接,预加载,get表单。

Set-Cookie: CookieName=CookieValue SameSite=Lax;

将SameSite设置为StrictLax时,就可以防止CSRF攻击了。

属性三:None属性:chrome默认将Lax设置为默认值,此时我们可以更改samesite的值,将其设置为none,此时必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。 下面是无效的:

Set-Cookie: widget_session=abc123  SameSite=None

下面是有效的:

Set-Cookie: widget_session=abc123 SameSite=None Secure;

8d22d47a7fa181e59e30535524de6a2.png 图中domain为cookie的属性

实际场景

  1.当我们登录之后,服务端就会创建一个属于当前用户的Session,里面保存的就是当前用户的信息;

  2.然后浏览器会根据服务器的响应头中Set-Cookie字段生成相关Cookie,相当于一个用户凭证;

  3.只需要在下次请求时携带这些Cookie,服务器就能通过Cookie来判断用户是否是登录状态,然后返回对应的响应。

二、JWT 认证机制

来源

Session 认证机制需要配合 Cookie 才能实现。由于 Cookie 默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域 Session 认证。

当前端请求后端接口不存在跨域问题的时候,推荐使用 Session 身份认证机制。 当前端需要跨域请求后端接口的时候,不推荐使用 Session 身份认证机制,推荐使用 JWT 认证机制。 复制代码

JWT的工作原理

首先client会发送用户名和密码给server,server会根据自己服务器内的secret密钥 + client的用户名和密码,通过哈希加密算法,生成一段JWT字符串,并且把这段字符串放回给client。此时这段JWT字符串server是不需要保存在数据库或这服务端的。那server是如何验证的呢?在下一次client提交用户名密码时会携带上之前生成的JWT字符串,server只需要在次通过哈希加密算法,来生成一段新的JWT字符串,在将这段新的字符串与client发回来的JWT字符串进行比对,如果一致的话,则验证成功。

这个哈希加密算法,在有secret密钥和用户名信息后,可以在很短时间内算出来JWT字符串,而如果只知道JWT字符串和用户名信息,则很难在有限的时间内算出来secret密钥,基本无法推出来。

所以我们会给JWT字符串定义一个限期,保证足够的安全性。

JWT的组成部分

JWT 通常由三部分组成,分别是 Header(头部)、Payload(有效荷载)、Signature(签名)。

三者之间使用英文的“.”分隔,格式如下:

例子:

JWT 的三个组成部分,从前到后分别是 Header、Payload、Signature。

其中:

Payload部分才是真正的用户信息,它是用户信息经过加密之后生成的字符串。 Header 和 Signature 是安全性相关的部分,只是为了保证 Token 的安全性。 复制代码

image.png