前言
最近在做一个登陆注册的功能,这个功能要用到JWT鉴权。提到鉴权又想到自己直接学的Cookie,Session,Token。就想干脆也用一篇文章小小的概括一下。
😋😋
用文章输出这种方式来记录学习过程,并且日后可以快速进行复习
认证和授权
初学者可能经常会把认证
和授权
混为一谈,这里就再捋一捋各自的关系。
什么是认证
-
指的是使用用户名和密码来验证当前用户的身份,简单来说就是用户登陆。> (比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功)* 互联网中的认证:* 用户名密码登录* 邮箱发送登录链接* 手机号接收验证码* 只要你能收到邮箱/验证码,就默认你是账号的主人什么是授权
-
指当用户登陆以后,当前用户是否有足够的权限访问特定的资源。> 你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息)* 实现授权的方式有:cookie、session、token、OAuthCookie
为什么会出现Cookie
HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息)
:每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人。所以服务器与浏览器为了进行会话跟踪(知道是谁在访问我),就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态需要通过 cookie 或者 session 去实现。
创建 Cookie
当接收到客户端发出的 HTTP 请求时,服务器可以发送带有响应的 Set-Cookie
标头,Cookie 通常由浏览器存储,然后将 Cookie 与 HTTP 标头一同向服务器发出请求。
看下面这个例子
Set-Cookie
HTTP 响应标头将 cookie 从服务器发送到用户代理。
现在,随着对服务器的每个新请求,浏览器将使用 Cookie 头将所有以前存储的 Cookie 发送回服务器。
Session
什么是Session
- session 是另一种记录服务器和客户端会话状态的机制
- session 是基于 cookie 实现的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中
Session认证流程
- 用户第一次请求
服务器
的时候,服务器根据用户提交的相关信息,创建对应的Session
* 请求返回时将此 Session 的唯一标识信息SessionID
返回给浏览器
*浏览器
接收到服务器
返回的SessionID
信息后,会将此信息存入到Cookie
中,同时Cookie
记录此SessionID
属于哪个域名* 当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在Cookie
信息,如果存在自动将Cookie
信息也发送给服务端,服务端会从Cookie
中获取SessionID
,再根据SessionID
查找对应的Session
信息,如果没有找到说明用户没有登录或者登录失效,如果找到Session
证明用户已经登录可执行后面操作。根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。
Token
什么是Token
- 访问资源接口(API)时所需要的资源凭证
- 简单 token 的组成:
uid
(用户唯一的身份标识)、time
(当前时间的时间戳)、sign
(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
Token 的身份验证流程
客户端
使用用户名跟密码请求登录*服务端
收到请求,去验证用户名与密码* 验证成功后,服务端
会签发一个token
并把这个token
发送给客户端
*客户端
收到token
以后,会把它存储起来,比如放在cookie
里或者localStorage
里*客户端
每次向服务端
请求资源的时候需要带着服务端
签发的token
*服务端
收到请求,然后去验证客户端
请求里面带着的token
,如果验证成功,就向客户端
返回请求的数据JWT
什么是JWT
JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。
JWT的认证流程
- 第一步,用户登陆,用户通过用户名和密码登陆,如果登陆成功,服务器就会返回一个加密文档,这个文档就是
jwt
,其中包含除了用户密码以外的全部的认证信息,包括用户名、email、角色、权限等等,而客户端在拿到jwt
以后就可以把它保存起来了,可以保存cookie
中,也可以保存在LocalStorage
里面,而生成jwt
以后不需要在服务器上保存。 - 第二步,用户需要访问某些资源,这个时候用户需要把
jwt
放在http请求
的header
中,与http请求
一同发送给服务器。服务器
取得jwt
以后,会使用自己的私钥
来给给jwt
文档解密,如果解密成功而且数据依然有效,则代表用户已经登陆了,如果jwt
所描述的用户权限允许该用户访问资源,服务器就会把资源信息通过http响应
发送回到客户端
。
什么时候用JWT
那么在真实工作中,我们要不要使用jwt
呢? 考虑一下下面的场景,大家应该都用过学校的学生系统吧,学生登录系统以后可以使用这个系统选课、查成绩什么的,如果现在学校又新建了一个图书馆系统,而且学校希望这个系统可以无缝衔接学生系统,使用同一套账户,在学生系统中登录以后就能直接进入图书馆系统。使用传统的session
验证方式,必须在学生系统和图书馆系统都各自创建一套session
才能实现登录,而各自的session
无法形成有效的联系,所以在最底层创建一个单点登录系统,不管学生访问哪个系统,都会连接到单点登录系统进行session
的验证,当学生的登录信息验证成功以后,单点登录系统会做一个重定向,把流量引导至相应的系统中。这样就可以实现这学生系统和图书馆系统的无缝连接。
但是,单点登录系统在使用分布式部署的时候又要考虑不同的服务器之间session
的一致性,从而导致系统架构非常复杂。
如果学校在建设学生系统的时候使用的是jwt
,那么想要拓展系统简直就是易如反掌。因为jwt
不会保存在服务器上,所以服务器如何部署完全不会影响到jwt
的使用。学生登录完成以后,把jwt
信息保存在浏览器中,需要访问学习系统或图书馆系统的时候,会向服务器发送带有jwt
的请求,学生系统和图书馆系统只需要使用相同的私钥来验证token
,验证成功以后,就可以通过token
中用户的权限给不同的用户输出不同的数据。
- 首先,无状态登录,简化服务器的用户验证流程,同时完美支持分布式部署。
- 第二,使用非对称加密,只要私钥不泄露,可以保证
token
是绝对安全的。
不过,jwt
也有两个非常明显的缺点,
- 第一,
jwt token
一经发布就无法挽回了,因为具有无状态的特征,所以在带来便利的同时也无法被服务禁用,也就是说,如果用户自身因为某些原因导致token
被黑客窃取,那么黑客就可以使用这个token
来伪装登录,而服务端对此没有任何办法,只能等待token
过期失效。 - 第二,
jwt
的前两个部分其实并没有加密,仅仅使用了base64
来编码而已,也就是说jwt
的用户信息等于是明文传递的,很容易造成用户的信息泄露。
最后
最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。
有需要的小伙伴,可以点击下方卡片领取,无偿分享