这是我参与「第四届青训营 」笔记创作活动的第5天
来源
一、Session 认证机制
HTTP是无状态协议
HTTP无状态是指?
HTTP协议对事务处理是没有记忆能力,也就是说服务器不知道客户端是什么状态。
这是什么意思呢?
当我们向服务器发送请求后,服务器解析处理请求,然后返回响应,服务器负责完成这个过程(也是一个事务),而这个过程是独立的,服务器不会记录前后状态的变化,也就是缺少状态记录。
无状态导致的后果?
意味着后续发出的请求需要处理前面请求的响应,则必须重传,这也导致需要额外传递一些前面的重复请求,才能获取后续响应。但为了保持前后状态,我们也不能将前面的请求全部重传一次,这太浪费资源了;就好像如果一个网站每次发出一个请求前都要先发出一次登录请求,这无疑大大增加了资源浪费程度。
什么是Cookie ?
Cookie是存储在用户浏览器中的一段不超过4 KB的字符串。它由一个名称(Name)、一个值(Value) 和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。
不同域名下的Cookie各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie 一同发送到服务器。
一些常见的cookie
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设置为Strict和Lax时,就可以防止CSRF攻击了。
属性三:None属性:chrome默认将Lax设置为默认值,此时我们可以更改samesite的值,将其设置为none,此时必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。 下面是无效的:
Set-Cookie: widget_session=abc123 SameSite=None
下面是有效的:
Set-Cookie: widget_session=abc123 SameSite=None Secure;
图中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 的安全性。 复制代码