token与JWT详细介绍

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

token介绍

Token 的中文意思是"令牌"。主要用来身份验证。比传统的身份验证方法Token 有扩展性强安全性高的特点非常适合用在 Web 应用或者移动应用上。

它是服务端生成的字符串作为客户端进行请求的一个标识。

token出现的背景

        以前Web 基本上就是文档的浏览而已每次请求都是一个新的HTTP协议 就是请求加响应尤其是我不用记住是谁刚刚发了HTTP请求。

        随着交互式Web应用的兴起像在线购物网站需要登录的网站等等面临一个问题必须记住哪些人登录系统也就是说我必须把每个人区分开这就是一个不小的挑战因为HTTP请求是无状态的起初想出的办法就是给每一个人发一个唯一的sessionid(一个随机的字符串)下次大家再向我发起HTTP请求的时候把这个sessionid带着 这样我就能区分开谁是谁了。

       每个人只需要保存自己的session id而服务器要保存所有人的session id 这对服务器说是一个巨大的开销 严重的限制了服务器扩展能力 比如说我用两个机器组成了一个集群 小F通过机器A登录了系统 那session id会保存在机器A上 假设小F的下一次请求被转发到机器B怎么办 机器B可没有小F的 session id啊。

        那只好做session 的复制了 把session id 在服务器之间搬来搬去 快累死了。

        于是有人就在思考 我为什么要保存这可恶的session id 只让每个客户端去保存多好

        可是如果不保存这些session id , 怎么验证客户端发给我的session id 的确是我生成的呢 如果不去验证我们都不知道他们是不是合法登录的用户 那些不怀好意的家伙们就可以伪造session id , 为所欲为了。所以关键点就是验证

        比如说 小F已经登录了系统 我给他发一个令牌(token) 里边包含了小F的 user id 下一次小F 再次通过Http 请求访问我的时候 把这个token 通过Http header 带过来

        不过这和session id没有本质区别啊 任何人都可以可以伪造 所以我得想点儿办法 让别人伪造不了。

        那就对数据做一个签名吧 比如说我用HMAC-SHA256 算法加上一个只有我才知道的密钥 对数据做一个签名 把这个签名和数据一起作为token 由于密钥别人不知道 就无法伪造token了。

        这个token服务器不保存当小F把这个token 给我发过来的时候我再用同样的HMAC-SHA256 算法和同样的密钥对数据再计算一次签名 和token 中的签名做个比较 如果相同 我就知道小F已经登录过了并且可以直接取到小F的user id , 如果不相同 数据部分肯定被人篡改过 我就告诉发送者 对不起没有认证。

        解除了session id这个负担 可以说是无事一身轻 我的机器集群现在可以轻松地做水平扩展 用户访问量增大 直接加机器就行。 这种无状态的感觉实在是太好了。

token对比session

这种基于token的认证方式相比传统的session认证方式更节约服务器资源并且对移动端和分布式更加友好。其优点如下

  • 支持跨域访问cookie是无法跨域的而token由于没有用到cookie(前提是将token放到请求头中)所以跨域后不会存在信息丢失问题
  • 无状态token机制在服务端不需要存储session信息因为token自身包含了所有登录用户的信息所以可以减轻服务端压力
  • 更适用CDN可以通过内容分发网络请求服务端的所有资料
  • 更适用于移动端当客户端是非浏览器平台时cookie是不支持的采用token认证方式会简单很多
  • 无需考虑CSRF由于不再依赖cookie所以采用token认证方式不会发生CSRF所以也就无需考虑CSRF的防御

JWT介绍

jwt是token的一种实现方式它将用户信息加密到token里服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性只要正确即通过验证。

优点

  • 简洁: 可以通过URL、POST参数或者在HTTP header发送因为数据量小传输速度也很快
  • 自包含负载中可以包含用户所需要的信息避免了多次查询数据库
  • Token是以JSON加密的形式保存在客户端的所以JWT是跨语言的原则上任何web形式都支持
  • 不需要在服务端保存会话信息特别适用于分布式微服务

缺点

  • 无法作废已颁布的令牌
  • 不易应对数据过期

示例

组成

JWT是由.分割的三部分组成

jwt token = base64 URL(头部) + "." +base64 URL(负载) + "." + base64 URL(签名)

Base64 URL是一种编码不是加密方式是可以解码的

头部Header

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg是签名用的算法默认为HMAC SHA256写为HS256JWT默认也是推荐的算法

  • typ属性表示令牌的类型JWT令牌统一写为JWT

负载Payload

JWT的主体内容部分也是JSON包含需要传递的数据

JWT指定七个默认字段供选择

iss发行人
exp到期时间
sub主题
aud用户
nbf在此之前不可用
iat发布时间
jtiJWT ID用于标识该JWT

除默认字段外我们还可以自定义字段一般会把包含用户信息的数据放到payload中如下

{
  "sub": "1234567890",
  "userID": "123456",
  "admin": true
}

JWT里不要存放敏感信息因为base64 URL编码是可以解码的

签名Signature

首先需要指定一个密钥(secretKey)该密钥只存在服务器中不能向用户公开公开使用header中指定的签名算法默认情况下为HMAC SHA256根据以下公式生成签名。

Signature = HS256(Base64(头部) + "." + Base64(负载) ,  secretKey)

jwt校验

header 和 payload可以直接利用base64 URL解码出原文。

从header中获取哈希签名的算法从payload中获取有效数据。

signature使用了不可逆的加密算法无法解码出原文它的作用是校验token有没有被篡改。服务端用header、payload、secretKey通过header中的签名算法进行再次加密比对加密后的数据和客户端发送过来token中的的是否一致。

无论改了头部、负载、和签名中的哪个部分token校验都不会通过

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6