原文连接:medium.com/vandium-sof…html
在本文中,将解释JSON Web Tokens(JWT)的基本原理以及使用缘由。 JWT 是确保应用程序信任和安全的重要部分。 JWT 容许以安全的方式表示诸如用户数据之类的声明。git
为了解释 JWT 如何工做,让咱们从一个抽象的定义开始。github
JSON Web令牌(JWT)是一种 JSON 对象,在 RFC 7519 中定义为在两方之间表示一组信息的安全方式。 JWT 由头部(header),负载(payload)和签名(signature)组成。web
简单地说,JWT只是一个具备如下格式的字符串:算法
header.payload.signature
复制代码
应该注意,双引号字符串被认为是有效的 JSON 对象。json
为了说明实际使用 JWT 的方式和缘由,咱们将使用一个简单的示例(参见下图)。 此示例中的三个不一样的实体是用户,应用程序服务器和身份验证服务器。 验证服务器将向用户提供 JWT。 使用 JWT,用户能够安全地与应用程序通讯。安全
应用程序如何使用JWT验证用户的真实性bash
在该示例中,用户首先使用认证服务器的登陆系统登陆认证服务器(例如,用户名和密码,Facebook登陆,Google登陆等)。 而后,身份验证服务器建立 JWT并将其发送给用户。 当用户对应用程序进行 API 调用时,用户将传递 JWT 以及 API 调用。 在这个实例中,应用程序服务器将能够验证传入的 JWT 是不是由身份验证服务器建立的(验证过程将在稍后更详细地说明)。当用户使用附加的 JWT 进行API 调用时,应用程序可使用 JWT 来验证该 API 调用是否来自通过身份验证的用户。服务器
如今,将更深刻地研究 JWT 自己及其构建和验证的方式。ide
JWT 的 Header 部分包含有关如何计算 JWT 签名的信息,是一个如下形式的 JSON 对象:
{
"typ": "JWT",
"alg": "HS256"
}
复制代码
在上面的 JSON 中,“typ”键的值指定对象是JWT,“alg”键的值指定用于建立 JWT 签名的算法。 在示例中,咱们使用 HMAC-SHA256算法(一种使用密钥的散列算法)来计算签名(在步骤3中会更详细的介绍)。
JWT 的 payload 部分时是存储在 JWT 内的数据。在咱们的示例中,身份验证服务器建立一个JWT,其中存储有用户信息,特别是用户ID。
{
"userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}
复制代码
The data inside the payload is referred to as the “claims” of the token.
在咱们的示例中,咱们只将一个声明放入 payload 中。 你能够根据须要添加任意数量的声明。JWT 规定了7个官方字段,供选用。
iss (issuer):签发人
exp (expiration time):过时时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
复制代码
除了官方字段,你还能够在这个部分定义私有字段。请记住,数据的大小将影响JWT的整体大小,这一般不是问题,但过大的 JWT 可能会对性能产生负面影响并致使延迟。
签名使用如下伪代码计算:
// signature algorithm
data = base64urlEncode( header ) + “.” + base64urlEncode( payload )
hashedData = hash( data, secret )
signature = base64urlEncode( hashedData )
复制代码
该算法所作的是 base64url 对在步骤1和2中建立的header和payload进行编码。而后,算法将获得的编码字符串用“点”(.)连在一块儿。
在示例中,header 和 payload 被 base64url 编码为:
// header
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
// payload
eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ
复制代码
而后,在加入周期的编码头和编码有效载荷上应用带有密钥的指定签名算法,咱们获得签名所需的散列数据。 在咱们的例子中,这意味着在数据字符串上应用 HS256 算法,并将密钥设置为字符串“secret”,以获取 hashedData字符串。 以后,经过base64url 编码 hashedData 字符串,咱们获得如下JWT签名:
// signature
-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM
复制代码
如今咱们已经建立了全部三个组件,咱们能够建立JWT。 记住JWT的header.payload.signature结构,咱们只须要组合以上的三个部分,用点(.)分隔它们。
// JWT Token
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM
复制代码
你能够尝试经过 jwt.io 建立本身的JWT。
回到咱们的示例,身份验证服务器如今能够将此 JWT 发送给用户。
要理解使用 JWT 的目的不是以任何方式隐藏或模糊数据,而是为了证实发送的数据是由真实的来源建立的。
如前面的步骤所示,JWT 内的数据是通过编码和签名的,而不是加密的。 编码数据的目的是转换数据的结构。 签名数据容许数据接收器验证数据源的真实性。 所以,编码和签名数据不会保护数据。 另外一方面,加密的主要目的是保护数据并防止未经受权的访问。 有关编码和加密之间差别的更详细说明,请参阅此文章。
因为 JWT 仅被签名和编码,而且因为 JWT 未加密,所以 JWT 不能保证敏感数据的安全性。
在咱们的示例中,咱们使用的是由 HS256 算法签名的JWT,其中只有身份验证服务器和应用服务器知道密钥。当应用程序设置其身份验证过程时,应用程序服务器从身份验证服务器接收密钥。因为应用程序知道密钥,当用户对应用程序进行带有 JWT 附加的 API 调用时,应用程序能够执行与 JWT 上的步骤3相同的签名算法。而后,应用程序能够验证从其本身的哈希操做得到的签名是否与 JWT 自己上的签名匹配(即,它与由认证服务器建立的 JWT 签名匹配)。若是签名匹配,则表示 JWT 有效,表示 API 调用来自可信源。不然,若是签名不匹配,则表示收到的 JWT 无效,这多是对应用程序的潜在攻击的指示。所以,经过验证 JWT,应用程序在其自身和用户之间添加了一层信任。
咱们了解了 JWT 是什么,如何建立和验证它们,以及如何使用它们来确保应用程序与其用户之间的信任。这是了解 JWT 基础知识及其有用之处的起点。 JWT 只是确保应用程序中的信任和安全性的难题之一。 应该注意,本文中描述的 JWT 身份验证设置使用对称密钥算法(HS256)。你也能够以相似的方式设置 JWT 身份验证,除非使用非对称算法(例如RS256),其中身份验证服务器具备密钥,而且应用程序服务器具备公钥。查看此 Stack Overflow问题,了解使用对称和非对称算法之间差别的详细分类。 还应该注意,JWT 应该经过 HTTPS 链接发送。拥有 HTTPS 有助于防止未经受权的用户经过使用它来窃取所发送的 JWT,从而没法拦截服务器和用户之间的通讯。 此外,在 JWT 中设置较短的过时时间十分重要,这样若是旧的 JWT 受到盗用,它们将被视为无效而且不能再使用。
《IVWEB 技术周刊》 震撼上线了,关注公众号:IVWEB社区,每周定时推送优质文章。