前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

JWT

作者头像
仇诺伊
发布2020-04-23 17:56:02
9130
发布2020-04-23 17:56:02
举报
文章被收录于专栏:佳爷的后花媛佳爷的后花媛

关于大部分互联网的认证流程:

上述模式在单机状态下没什么问题,但是如果是在服务器集群或者跨域的情况下,就没什么优势了。

举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?

一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

■ ■■■■

JWT

JWT 是 JSON Web Token 的缩写,是一个非常轻巧的规范,这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。

JWT 由头部(header)、载荷(payload)与签名(signature)组成,一个 JWT 类似下面这样:

其中:

Header 部分是一个 JSON 对象,描述 JWT 的元数据,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。

代码语言:javascript
复制
{(header)
   "typ":"JWT",
   "alg":"HS256"
}

{
   "iss":"http://larabbs.test",
   "iat":1515733500,
   "exp":1515737100,
   "nbf":1515733500,
   "jti":"c3U4VevxG2ZA1qhT",
   "sub":1,
   "prv":"23bd5c8949f600adb39e701c400872db7a5976f7"
}
signature
  • 头部申明了加密算法;
  • 载荷中有两个比较重要的数据,exp 是过期时间,sub 是 JWT 的主体,这里就是用户的 id;
  • 最后的 signature 是由服务器进行的签名,保证了 token 不被篡改。

除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。

代码语言:javascript
复制
{
 "sub": "1234567890",
 "name": "John Doe",
 "admin": true
}

Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

代码语言:javascript
复制
HMACSHA256(
 base64UrlEncode(header) + "." +
 base64UrlEncode(payload),
 secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

实际的JWT长这样:

它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。

JWT 最后是通过 Base64 编码的,也就是说,它可以被翻译回原来的样子来的。所以不要在 JWT 中存放一些敏感信息。

用户 id,过期时间等数据都保存在 Token 中了,所以并不需要将 Token 保存在服务器中,客户端请求的时候在 Header 中携带 Token,服务器获取 Token后,进行 base64_decode 即可获取数据进行校验,由于已经有了签名,所以不用担心数据被篡改。

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

代码语言:javascript
复制
Authorization: Bearer <token>

另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

Token 验证

有了 token 之后该如何验证 token 的有效性,并得到 token 对应的用户呢?其实原理很简单,DingoApi 为我们准备好了 api.auth 这个中间件.

  • 获取客户端提交的 token
  • 检测 token 中的签名 signature 是否正确
  • 判断 payload 数据中的 exp,是否已经过期
  • 根据 payload 数据中的 sub,取数据库中验证用户是否存在
  • 上述检测不正确,则抛出相应异常

参考资料:

JSON Web Token - 在Web应用间安全地传递信息

阮一峰的日志

Sessionless Authentication using JWTs

Basic

基础

数组函数

  • array_change_key_case — 将数组中的所有键名修改为全大写或小写
  • array_chunk — 将一个数组分割成多个
  • array_column — 返回数组中指定的一列
  • array_combine — 创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值
  • array_count_values — 统计数组中所有的值
  • array_diff_assoc — 带索引检查计算数组的差集
  • array_diff_key — 使用键名比较计算数组的差集
  • array_diff_uassoc — 用用户提供的回调函数做索引检查来计算数组的差集
  • array_diff_ukey — 用回调函数对键名比较计算数组的差集
  • array_diff — 计算数组的差集

end

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 佳爷的后花媛 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Token 验证
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档