一、什么是身份认证?

身份认证(Authentication)又称“身份验证”、“鉴权”,是指通过一定的手段,完成对用户身份的确认。
日常生活中的身份认证随处可见,例如:高铁的验票乘车,手机的密码或指纹解锁,支付宝或微信的支付密码等。
在Web开发中,也涉及到用户身份的认证,例如:各大网站的手机验证码登录、邮箱密码登录、二维码登录等。

二、为什么需要身份认证?

  身份认证的目的,是为了确认当前所声称为某种身份的用户,确实是所声称的用户。
  例如,你去找快递员取快递,你要怎么证明这份快递是你的。
  一句话:如何证明你是你?

三、Session认证机制

  1.HTTP请求的无状态性
    HTTP 协议的无状态性,指的是客户端的每次 HTTP 请求都是独立的,连续多个请求之间没有直接的关系,服务器不会主动保留每次 HTTP 请求的状态。
  2.使用 Cookie 突破 HTTP 请求的无状态性
    2.1 什么是 Cookie
      Cookie 是存储在用户浏览器中的一段不超过 4 KB 的字符串。它由一个名称(Name)、一个值(Value)和其它几个用于控制 Cookie 有效期、安全性、使用范围的可选属性组成。
      不同域名下的 Cookie 各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的 Cookie 一同发送到服务器。
    2.2 Cookie的四大特点
      自动发送,域名独立,过期时限,4KB大小限制
  3.Cookie 在身份认证中的作用
    客户端第一次请求服务器的时候,服务器通过响应头的形式,向客户端发送一个身份认证的 Cookie,客户端会自动将 Cookie 保存在浏览器中。
    随后,当客户端浏览器每次请求服务器的时候,浏览器会自动将身份认证相关的 Cookie,通过请求头的形式发送给服务器,服务器即可验明客户端的身份。

  

  4. Cookie 不具有安全性
    由于 Cookie 是存储在浏览器中的,而且浏览器也提供了读写 Cookie 的 API,因此 Cookie 很容易被伪造,不具有安全性。
    因此不建议服务器将重要的隐私数据,通过 Cookie 的形式发送给浏览器。
  5. 提高身份认证的安全性---Session认证机制

  

  6.Session认证的局限性
    Session 认证机制需要配合 Cookie 才能实现。由于 Cookie 默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域 Session 认证。
  7.Cookie与Session的区别
  (1)存储位置不同:
    Cookie 存储在浏览器当中,Session 存储在服务器当中。
  (2)安全性不同
    Cookie 存储在浏览器中,浏览器提供获取和修改 Cookie 的API,使得Cookie很容易遭到篡改,而 Session 保存在服务器当中,相对Cookie更加安全。
  (3)有效期不同
    Cookie 的有效期很久,甚至可以是永久,但是Session为了减轻服务器的压力,会定期清除长时间没有被访问过的(超时的)Session以减轻服务器压力。
  (4)对服务器压力不同
    Session保存在服务器,每个用户都有一个Session,如果访问量过大,用户过多,会对服务器造成压力。Cookie保存在客户端,不占用服务器资源。

四、JWT认证机制

  1.JWT的工作原理

  

  总结:用户的信息通过 Token 字符串的形式,保存在客户端浏览器中。服务器通过还原 Token 字符串的形式来认证用户的身份。
  2.JWT的组成部分
    JWT 的三个组成部分,从前到后分别是 Header、Payload、Signature。
    Payload 部分才是真正的用户信息,它是用户信息经过加密之后生成的字符串。
    Header 和 Signature 是安全性相关的部分,只是为了保证 Token 的安全性。
  3. JWT 的使用方式
    客户端收到服务器返回的 JWT 之后,通常会将它储存在 localStorage 或 sessionStorage 中。
    此后,客户端每次与服务器通信,都要带上这个 JWT 的字符串,从而进行身份认证。推荐的做法是把 JWT 放在 HTTP 请求头的 Authorization 字段中。

五、Session认证机制与JWT认证机制应用场景

  服务端渲染、不跨域时推荐使用Session
  前后端分离、跨域时推荐使用JWT

六、Cookie/Session和JWT的优缺点

  三者共同点:三者都是应用在web中对http无状态协议的补充,达到状态保持
    cokkie:cookie中的信息是以键值对的形式储存在浏览器中的,而且在浏览器中可以直接看到数据
    session:session存储在服务器中,然后发送一个cookie存储在浏览器中,cookie中存储的是session_id通过session_id请求服务器可以获取对应的session信息.
    jwt:由服务器产生加密的json数据包括,header,payload,signature三部分组成,header中通常来说由token的生成算法和类型组成。
    payload中则用来保存相关的状态信息。signature部分由header,payload,secret_key三部分加密生成。
  1、存储差异
    cookie信息和jwt存储在客户端,session信息存储在服务端,但是cookie是浏览器客户端独有的。
  2、优劣
    2.1、cookie:
    cookie优点:
      2.1.1:简单性 Cookie 是一种基于文本的轻量结构,包含简单的键值对。
      2.1.2:数据持久性 虽然客户端计算机上 Cookie 的持续时间取决于客户端上的 Cookie 过期处理和用户干预,Cookie 通常是客户端上持续时间最长的数据保留形式。
    cookie缺点:
      2.1.3:大小受到限制 ,大多数浏览器对 Cookie 的大小有 4096 字节的限制,尽管在当今新的浏览器和客户端设备版本中,支持 8192 字节的 Cookie 大小已愈发常见。
      2.1.4:非常不安全,cookie将数据裸露在浏览器中,这样大大增大了数据被盗取的风险,所有我们不应该将中要的数据放在cookie中,或者将数据加密处理。
      2.1.5:容易被csrf攻击,可以设置csrf_token来避免攻击。
    2.2、session:
    session优点:
      2.2.1:session中的信息存储在服务端,相比于cookie就在一定程度上加大了数据的安全性。
      2.2.2:session数据存储在服务端,相比于jwt方便进行管理,也就是说当用户登录和主动注销,只需要添加删除对应的session就可以,这样管理起来很方便。
    session缺点:
      2.2.3:session存储在服务端,这就增大了服务器的开销,当用户多的情况下,服务器性能会大大降低。
      2.2.4:因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
      2.2.5:用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,
          这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
    2.3、jwt:
    jwt优点:
      2.3.1:因为json的通用性,jwt可以支持跨语言请求,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
      2.3.2:因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
      2.3.3:便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
      2.3.4:它不需要在服务端保存会话信息, 所以它易于应用的扩展,即信息不保存在服务端,不会存在session扩展不方便的情况。
    jwt缺点:
      2.3.5:登录状态信息续签问题。比如设置token的有效期为一个小时,那么一个小时后,如果用户仍然在这个web应用上,这个时候当然不能指望用户再登录一次。
         目前可用的解决办法是在每次用户发出请求都返回一个新的token,前端再用这个新的token来替代旧的,这样每一次请求都会刷新token的有效期。
         但是这样,需要频繁的生成token。这个方法不仅暴力不优雅,而且每次请求都要做jwt的加密解密,会带来性能问题。
         另一种方法是在redis中单独为每个jwt设置过期时间,每次访问时刷新jwt的过期时间。
      2.3.6:用户主动注销。JWT并不支持用户主动退出登录,当然,可以在客户端删除这个token,但在别处使用的token仍然可以正常访问。
         为了支持注销,我的解决方案是在注销时将该token加入黑名单。
    使用jwt注意点:
      2.3.7:在payload中不应该存放敏感信息,以为该部分客户端是可以解密的。
      2.3.8:secret_key不能泄露。
    适合使用jwt的场景:
      2.3.9:有效期短
      2.3.10:只希望被使用一次
      比如,用户注册后发一封邮件让其激活账户,通常邮件中需要有一个链接,这个链接需要具备以下的特性:
      能够标识用户,该链接具有时效性(通常只允许几小时之内激活),不能被篡改以激活其他可能的账户,一次性的。这种场景就适合使用jwt。
      而由于jwt具有一次性的特性。单点登录和会话管理非常不适合用jwt,如果在服务端部署额外的逻辑存储jwt的状态,那还不如使用session。
      基于session有很多成熟的框架可以开箱即用,但是用jwt还要自己实现逻辑。

参考:

https://blog.csdn.net/qq_59181609/article/details/125731296

https://cloud.tencent.com/developer/article/1773610

https://blog.csdn.net/weixin_61422097/article/details/120454714

token可以存储在cookie中吗

https://www.nowcoder.com/exam/interview/detail?questionClassifyId=0&questionId=2412490&questionJobId=156&type=1