引言

前文介绍了 Session-Cookie 的认证过程,简单回顾下基本步骤:

  1. 客户端(浏览器)向服务器发送用户名和密码
  2. 服务器验证通过后,创建 Session 对象,在 Session 中保存该用户相关的数据,比如用户角色、登录时间等等
  3. 服务器向用户返回这个 Session 对象的唯一标识 SessionId,并写入客户端的 Cookie
  4. 客户端随后的每一次请求,都会通过 Cookie,将 SessionId 传回服务器
  5. 服务器收到 SessionId,并据此找到 Session 对象,由此获取到用户信息

这种方法的缺点就是分布式集群情况下无法保证每台服务器都拥有相同的 Session,上篇文章也简单介绍了几种 Session 如何在多个服务器之间共享的方法。

显然,Session 的维护给服务端造成了很大的困扰,有没有更好的方案,能不能直接不用 Session?

为此,Token 应运而生。

30s 图解 Token 认证

首先,什么是 Token?

简单来说,Token 其实就是一串字符串,一个令牌,客户端访问服务器时,验证通过后服务端会为其签发一张令牌,之后,客户端就可以携带这个令牌访问服务器,服务端只需要验证令牌的有效性即可。

一般来说,Token 的组成是这样的:

uid (用户唯一的身份标识) + time (当前时间的时间戳) + sign (签名,Token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)

基于 token 的认证步骤如下图,配合文字食用:

1)客户端(浏览器):用户向服务器发送登录信息(用户名和密码)来请求登录校验;

2)服务端:验证用户名密码等,验证成功后生成 token 并返回给前端,这个 token 就是之后鉴权的唯一凭证。服务端需要将这个 token 及其对应的用户信息存储在数据库或者缓存中;

3)客户端:将服务端返回的 token 存在 cookie 或者 localStorge 中,之后的每次请求之前,从 cookie 或者 localStorge 取出 token 将其设置进 HTTP Header 中(可以通过 HTTP 请求拦截器实现);

4)服务端:服务端接收到来自客户端的请求,从 HTTP Header 中取出 token,去缓存或者数据库中进行验证(该 token 是否存在 / 根据该 token 能否找到对应的用户),如果验证通过则执行进一步的业务操作,如果不通过则拒绝执行。

附加阅读

Token 认证服务端代码

先来看登录,就是先判断用户名密码是否正确,如果正确,那么会生成并返回一个字符串做为 token(这里偷个懒就直接用 UUID 来生成了),并将其和用户信息(这里就简单的存了 username)一并存入到数据库 or 缓存中(这里采用 Redis,过期时间可自行配置)。

退出登录实质就是删除 Redis 中存储的 token,完整内容如下:

再来个拦截器,前端拿到后端返回的 token 后每次请求前都会在 HTTP header 中带上这个 token,服务端设置个拦截器取出 Header 中的token,然后去 Redis 中进行判断这个 token 是否存在,若存在则允许进行下一步操作,:

Refresh Token

一般来说,为了安全起见,防止 token 被攻击者盗用,token 的有效期不会设置的太长,这样就会由于 token 过期导致用户需要重新登录从而生成新的 token。

如何才能做到不需要用户去频繁的登录呢,Refresh Token 机制出现了。

我们把之前的那个 Token 称之为 Access Token,业务接口用这个 Access Token 进行认证鉴权

而 Refresh Token 呢,就是一个专门用来在 Access Token 过期后重新获取新的 Access Token 的 Token

Refresh Token 的过期时间设置的长一点比如一两个月,Access Token 的过期时间设置短一点比如一周,这样可以缩短 Access Token 的过期时间保证安全,同时又不会因为频繁过期重新要求用户登录

具体认证步骤如下图,配合文字食用:

1)客户端(浏览器):用户向服务器发送登录信息(用户名和密码)来请求登录校验;

2)服务端: 验证用户名密码等,验证成功后生成 Access Token 和 Refresh Token 并返回给前端,服务端需要将这两个 token 及其对应的用户信息存储在数据库或者缓存中;

3)客户端: 将服务端返回的 Access Token 和 Refresh Token 存在 cookie 或者 localStorge 中,之后的每次请求之前,从 cookie 或者 localStorge 取出 Access Token 将其设置进 HTTP Header 中(可以通过 HTTP 请求拦截器实现);

4)服务端:

  • 验证 Access Token 有效:正常返回数据
  • 验证 Access Token 过期:拒绝请求
    • 客户端:重新发起请求,在 HTTP Header 中携带 Refresh Token 发送给服务端
    • 服务端:验证客户端传来的 Refresh Token ,验证成功后生成新的 Access Token 并返回给客户端
    • 客户端:获得服务端返回的新的 Access Token,重新发起请求并携带新的 Access Token

如何理解 Refresh Token 的必要性,或者说为什么使用 Refresh Token 能够更安全?

  • Access Token 每次访问都要带着,因此更容易被盗取
  • 而 Refresh Token 客户端获取到之后就保存起来,Access Token 失效之后,才会用到 Refresh Token,所以粗略来说 Refresh Token 只会在网络上传输两次,一次是你获取的时候,一次是你使用的时候(从上图可以看出来),因此 Refresh Token 被盗的风险远远小于 Access Token

小伙伴们大家好呀,本文首发于公众号@飞天小牛肉,阿里云 & InfoQ 签约作者,分享大厂面试原创高质量题解、原创技术干货和成长经验。回复『春秋招』我拉你进求职吹水交流群,回复『简历修改』免费获取简历修改服务,回复『Echo』免费获取社区项目手把手教程)

收留 2023 秋招伤心人,秋招补录 & 春招强势开启,现在不投年后要被冲烂啦,信息汇总长期更新:小牛肉 x 互联网春招 & 秋招补录信息汇总

如何用 30s 给面试官讲清楚什么是 Token的更多相关文章

  1. 面试官所问的--Token认证

    写这一篇文章的来源是因为某一天的我被面试官提问:让你设计一个登录页面,你会如何设计? 我当时的脑子只有??? 不就是提交账号.密码给后台就搞定了呢? 不可能那么简单,我弱弱的想,难道要对密码加密?? ...

  2. 我是如何用 ThreadLocal 虐面试官的?

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. Thr ...

  3. 如何用json 与jsonp 的区别去回答你的面试官?

    常常 有面试官这样问我们,虽然用过无数次,但是回答不上岂不是尴尬,那我们浅析一下它们的区别? 1. json JSON是一种基于文本的数据交换格式,用于描述复杂的数据,举个例子: var nax=[ ...

  4. 引用面试官文章 :如何准备Java初级和高级的技术面试

    本人最近几年一直在做java后端方面的技术面试官,而在最近两周,又密集了面试了一些java初级和高级开发的候选人,在面试过程中,我自认为比较慎重,遇到问题回答不好的候选人,我总会再三从不同方面提问,只 ...

  5. java面试官如何面试别人

                                                                                      java面试官如何面试别人(一) j ...

  6. 8年经验面试官详解 Java 面试秘诀

      作者 | 胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三 ...

  7. 一个资深java面试官的“面试心得”

    在公司当技术面试官几年间,从应届生到工作十几年的应聘者都遇到过.先表达一下我自己对面试的观点: 1.笔试.面试去评价一个人肯定是不够准确的,了解一个人最准确的方式就是“路遥知马力,日久见人心”.通过一 ...

  8. iOS开发,这样写简历才能让大厂面试官看重你!

    前言: 对于职场来说,简历就如同门面.若是没想好,出了差错,耽误些时日倒不打紧,便是这简历入不了HR的眼,费力伤神还不能觅得好去处,这数年来勤学苦练的大好光阴,岂不辜负? 简历,简而有力.是对一个人工 ...

  9. (转)史上最全 40 道 Dubbo 面试题及答案,看完碾压面试官!

    背景:因为自己的简历写了dubbo,面试时候经常被问到.实际自己对dubbo的认识只停留在使用阶段,所以有必要好好补充下基础的理论知识. https://zhuanlan.zhihu.com/p/45 ...

  10. 面试官问我,使用Dubbo有没有遇到一些坑?我笑了。

    前言 17年的时候,因为一时冲动没把持住(当然最近也有粉丝叫我再冲动一把再更新一波),结合面试题写了一个系列的Dubbo源码解析.目前公众号大部分粉丝都是之前的粉丝,这里不过多介绍. 根据我的面试经验 ...

随机推荐

  1. MybatisPlus生成主键策略方法

    MybatisPlus生成主键策略方法 全局id生成策略[因为是全局id所以不推荐] SpringBoot集成Mybatis-Plus 在yaml配置文件中添加MP配置 mybatis-plus: g ...

  2. 精简docker的导出镜像

    Docker 镜像是由多个文件系统(只读层)叠加而成,每个层仅包含了前一层的差异部分.当我们启动一个容器的时候,Docker 会加载镜像层并在其上添加一个可写层.容器上所做的任何更改,譬如新建文件.更 ...

  3. HTML5+CSS3常见布局方式

    1.等高布局 1.1 代码 等高布局是指子元素在父元素中高度相等的布局方式 <div class="father"> <div class="f1&qu ...

  4. miniconda使用

    基本指令 conda create -n xxx python=3.7 // 创建Python3.7的名为xxx虚拟环境 conda env list // 显示所有的虚拟环境 conda activ ...

  5. fastposter v2.10.0 简单易用的海报生成器

    fastposter海报生成器是一款快速开发海报的工具.只需上传一张背景图,在对应的位置放上组件(文字.图片.二维.头像)即可生成海报. 点击代码直接生成各种语言的调用代码,方便快速开发. 现已服务众 ...

  6. Git 分支管理策略汇总

    原文链接: Git 分支管理策略 最近,团队新入职了一些小伙伴,在开发过程中,他们问我 Git 分支是如何管理的,以及应该怎么提交代码? 我大概说了一些规则,但仔细想来,好像也并没有形成一个清晰规范的 ...

  7. Go语言核心36讲41

    你好,我是郝林,今天我们继续分享bytes包与字节串操作的相关内容. 在上一篇文章中,我们分享了bytes.Buffer中已读计数的大致功用,并围绕着这个问题做了解析,下面我们来进行相关的知识扩展. ...

  8. 视觉享受,兼顾人文观感和几何特征的字体「GitHub 热点速览 v.22.46」

    GitHub 上开源的字体不在少数,但是支持汉字以及其他非英文语言的字体少之又少,记得上一个字体还是 霞鹜文楷,本周 B 站知名设计 UP 主开源了的得意黑体在人文观感和几何特征之间找到了美的平衡. ...

  9. qtcreator配置cmake+mingw开发环境

    环境准备 cmake 添加到PATH环境变量. mingw: 这里我用的mingw是Qt自带的,我将其添加到PATH环境变量中. 在cmd中执行 mingw32-make.exe 和 cmake查看命 ...

  10. 6. PyQt5 中的多线程的使用(上)

    专栏地址 ʅ(‾◡◝)ʃ 这一节引入了多线程这个非常重要概念, 在我认为多线程的重要性是紧紧次于信号与槽函数的, 因为在平时经常使用 1. 为什么要用多线程 先看下面这一个示例代码 6.1 from ...