基于Token的身份验证的方法
作者:王皓 发布时间:2023-09-27 19:05:41
最近了解下基于 Token 的身份验证,跟大伙分享下。很多大型网站也都在用,比如 Facebook,Twitter,Google+,Github 等等,比起传统的身份验证方法,Token 扩展性更强,也更安全点,非常适合用在 Web 应用或者移动应用上。Token 的中文有人翻译成 “令牌”,我觉得挺好,意思就是,你拿着这个令牌,才能过一些关卡。
传统身份验证的方法
HTTP 是一种没有状态的协议,也就是它并不知道是谁是访问应用。这里我们把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证一下。
解决的方法就是,当用户请求登录的时候,如果没有问题,我们在服务端生成一条记录,这个记录里可以说明一下登录的用户是谁,然后把这条记录的 ID 号发送给客户端,客户端收到以后把这个 ID 号存储在 Cookie 里,下次这个用户再向服务端发送请求的时候,可以带着这个 Cookie ,这样服务端会验证一个这个 Cookie 里的信息,看看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。
上面说的就是 Session,我们需要在服务端存储为登录的用户生成的 Session ,这些 Session 可能会存储在内存,磁盘,或者数据库里。我们可能需要在服务端定期的去清理过期的 Session 。
基于 Token 的身份验证方法
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
JWT
实施 Token 验证的方法挺多的,还有一些标准方法,比如 JWT,读作:jot ,表示:JSON Web Tokens 。JWT 标准的 Token 有三个部分:
header
payload
signature
中间用点分隔开,并且都会使用 Base64 编码,所以真正的 Token 看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
Header
header 部分主要是两部分内容,一个是 Token 的类型,另一个是使用的算法,比如下面类型就是 JWT,使用的算法是 HS256。
{
"typ": "JWT",
"alg": "HS256"
}
上面的内容要用 Base64 的形式编码一下,所以就变成这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。下面是标准字段:
iss:Issuer,发行者
sub:Subject,主题
aud:Audience,观众
exp:Expiration time,过期时间
nbf:Not before
iat:Issued at,发行时间
jti:JWT ID
比如下面这个 Payload ,用到了 iss 发行人,还有 exp 过期时间。另外还有两个自定义的字段,一个是 name ,还有一个是 admin 。
{
"iss": "ninghao.net",
"exp": "1438955445",
"name": "wanghao",
"admin": true
}
使用 Base64 编码以后就变成了这个样子:
eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ
Signature
JWT 的最后一部分是 Signature ,这部分内容有三个部分,先是用 Base64 编码的 header.payload ,再用加密算法加密一下,加密的时候要放进去一个 Secret ,这个相当于是一个密码,这个密码秘密地存储在服务端。
header
payload
secret
var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);
HMACSHA256(encodedString, 'secret');
处理完成以后看起来像这样:
SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
最后这个在服务端生成并且要发送给客户端的 Token 看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
客户端收到这个 Token 以后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,然后进行验证,通过以后就会返回给客户端想要的资源。
相关链接
http://jwt.io/
https://github.com/firebase/php-jwt
https://scotch.io/tutorials/the-anatomy-of-a-json-web-token
https://github.com/auth0/jwt-decode
来源:https://ninghao.net/blog/2834


猜你喜欢
- 本文实例讲述了Python实现MySQL操作的方法。分享给大家供大家参考,具体如下:1. 安装MySQLdb.从网站下载Mysql for
- 一、原理1.图片必须具有经纬度信息2.经纬度格式转换2.1 GPS点坐标的两种表示方式(误差还是有的)2.1.1 十进制换度分秒例:经纬度1
- 一. ADO.NET的定义ADO.NET来源于COM组件库ADO(即ActiveX Data Objects),是微软公司新一代.NET数据
- ipython notebook经常被我用作debug的工具。今天调试一段代码,里面用到了argparse这个包来解析命令行参数。但是在ip
- 以前在使用Python的时候,都是使用root用户安装好的全局python,现在,因为root用户安装的Python版本太低,同时自己没有r
- 一、基础概述机器学习(Machine Learing)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。机
- 在windows 2003下,在运行web应用程序的时候出现一下错误: 服务器无法处理请求,-->对路径“C:/temp/mytest.tx
- 本文实例讲述了python通过pil模块获得图片exif信息的方法。分享给大家供大家参考。具体分析如下:python的pil模块功能超级强大
- 首先,必须有错误继续进行的声明On Error Resume Next 然后尝试简历jmail实例: Dim JMail Set JMail
- 这篇文章主要介绍了通过实例解析Python调用json模块,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- 1. select模块针对select,要先理解其他几个概念:文件描述符:文件描述符在形式上是一个非负整数。实际上,它是一个索引
- 前言首先抛出几个问题:console.log(Boolean({}));console.log(Number([]));console.lo
- 步骤——1:定位在通过与客户,或与和客户接触的业务人员交流,做出一个准确的定位.定位的准确与否,虽然不能决定一定通过,但如果定位不准或相差太
- 使用MySQL Administrator 登录,报错: Either the server service or the configur
- 本文给出了本人在使用 Sublime Text 配置 Python 环境的记录。主要为了解决中文乱码的问题以及 Sublime Text 默
- 在Python中,数据存储方式分为同步存储和异步存储。同步写入速度比较慢,而爬虫速度比较快,有可能导致数据保存不完整,一部分数据没有入库。而
- 这篇文章中我们将通过对HelloWorld的message进行操作,介绍一下如何使用flask进行Restful的CRUD。概要信息事前准备
- 本文实例讲述了Python面向对象程序设计之类和对象、实例变量、类变量用法。分享给大家供大家参考,具体如下:类和对象:类的定义:用来描述具有
- truncate table 表名 ( 数据不可恢复性的删除 truncate 标识列会重排 ) LinqUtil.Db.ExecuteCo
- 1.open使用open打开文件后一定要记得调用文件对象的close()方法。比如可以用try/finally语句来确保最后能关闭文件。fi