|
|
51CTO旗下网站
|
|
移动端

浅显易懂讲解如何用JWT来加固API

本文通过浅显易懂的方式,向您阐述了如何用JSON Web Token来加固API。

作者:陈峻编译来源:51CTO|2019-05-10 09:00

【51CTO.com快译】您一定听说过JSON Web Token(JWT)吧? 它是当前用来保护API的最先进技术之一。与大多数安全概念与技术一样,我们在准备使用它之前,了解其工作原理是非常必要且重要的。当然,过于专业和技术性的JWT解释可能会让您觉得费解,甚至感到头痛。那么让我试着用一种比较浅显易懂的方式,向您阐述JWT是如何加固API的吧。

浅显易懂讲解如何用JWT来加固API

API身份验证

不言而喻,在复杂的开户免费送彩金38元环境中,我们需要对各种API资源实施访问限制。例如,我们不希望某个用户能够更改另一个用户的密码。那么,我们就需要该用户以提交其ID和密码的方式,来保护和加固目标资源。换句话说:我们需要对他们进行身份验证。

而在实际应用中,我们保护HTTP类API的难点在于:各种请求是无状态的。也就是说:API无法知道任意两个请求是否来自同一个用户。有人可能会追问:我们为什么不能要求用户在每次调用API时,都提供他们的ID和密码呢?答案是:因为这样会给用户带来极差的访问体验。

JSON Web Token

因此,我们需要的是:用户只用一次性提供信任凭据,而在后续的请求中,服务器会以另一种方式进行用户身份的识别。基于这种思想,JSON Web Token应运而生。

当然,如果您是一位爱好钻研的学霸,那么您可以通过链接:https://robmclarty.com/blog/what-is-a-json-web-token,来对JSON Web Token的工作原理进行全面深入的参悟。

在此让我们想象一下:如果您打算入住一家酒店,那么“令牌”就是允许您进入自己房间、以及酒店内其他设施的安全门卡,显然您不能进入其他人的房间。而且在退房的时候,您需要退还门卡,即:注销。

令牌的结构

通常情况下, JSON Web Token是通过各种HTTP请求的头部(header)被发送的。如下所示:

  1. Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U 

可见,令牌就是“Authorization:Bearer”的后面部分,隶属于HTTP的头部信息。

上述信息虽然显得比较凌乱,不过它包含了如下部分:

首先,令牌由三个不同的字符串所组成,它们分别以点号隔开。这三个字符串使用了base 64编码,分别对应头部(header)、有效载荷(payload)和签名(signature),如下所示:

  1. // Header  
  2. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 
  3. // Payload 
  4. eyJzdWIiOiIxMjM0NTY3ODkwIn0 
  5. // Signature 
  6. dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U 

注:base 64是一种转换字符串的方法,能够确保字符串在跨Web传输的过程中不会出现问题。由于它不是一种加密方法,因此任何人都可以很容易地对它进行解码,以查看原始数据。

下面,我们对上述字符串进行解码,以便更好地了解JWT的结构。

头部

通过解码令牌的头部,我们可以得到如下的元信息(meta information)。由于它对于我们理解整体的工作原理帮助不大,所以我们在此并不做详细解读。

  1.   "alg":"HS256", 
  2.   "typ":"JWT" 

有效载荷

有效载荷里的内容要丰富得多。您可以用它来包含任何自己需要传递的数据。在此,由于该令牌的目的是对API的访问进行身份验证,因此仅包含了用户的ID。

  1.   "userId":"1234567890" 

值得注意的是:有效负载并不安全。任何人都可以通过解码令牌,来查看有效负载中的确切内容。因此,我们通常只包含ID,而不会包含诸如用户邮件内容等敏感的标识信息。

尽管该有效负载为API提供了识别用户所需的全部信息,但是它并不提供具体的身份验证方法。毕竟凭借这些信息,攻击者足以能够轻松地找到用户的ID,并可伪造出令牌。因此,我们还需要有签名,而它才是令牌认证环节中的关键部分。

哈希算法

在开始解释签名的工作原理之前,我们需要先来了解一下什么是哈希算法。

首先,它是一个函数,可用来将目标字符串转换为另一种被称为哈希值(hash)的新字符串。例如,我们对字符串“Hello, world.”进行哈希操作,那么就能够得到如下经过了SHA256哈希算法的输出:

  1. 4ae7c3b6ac0beff671efa8cf57386151c06e58ca53a78d83f36107316cec125f 

注:哈希算法有许多种不同的类型,JWT常用的是SHA256。

而哈希的最重要属性在于:我们无法使用哈希算法,通过哈希值来识别出原始的字符串。换句话说,我们无法凭借上述哈希值,直接注册短信验证送体验金或得出原始的字符串“Hello, world.”。从理论上说,根据哈希的复杂性,猜测出原始字符串是完全不可行的。

JWT签名

现在,让我们来看JWT令牌结构的第三个部分:签名。实际上,该部分是需要进行注册短信验证送体验金的。

  1. HMACSHA256( 
  2.   base64UrlEncode(header) + "." + base64UrlEncode(payload), 
  3.   "secret string" 
  4. ); 

我们下面来具体分析一下上述代码:

  • 首先,HMACSHA256是哈希函数的名称,它用到了两个参数:需要进行哈希的字符串和密钥(secret)。
  • 其次,这个需要进行哈希的字符串,是经过base 64编码过的头部和有效载荷。
  • 第三,密钥是一串任意数据,而且只有服务器知晓。

问:为什么要将头部和有效载荷添加到签名的哈希值中呢?

答:这样可以确保签名对于该特定令牌来说是唯一的。

问:什么是密钥?

答:让我们从如何伪造一个令牌的角度来回答该问题。我们之前说过,攻击者无法从输出值来推导出经过哈希的输入信息。但是,由于签名中包括了头部和有效载荷,而这些都是公共的信息,因此如果攻击者知道了哈希算法(这通常是在头部被指定的),那么就能够生成相同的哈希值。

可见,如果服务器掌握了某个非公开的密钥,并且将其包含在哈希处理的过程中,那么就能够防止攻击者自行伪造并生成带有哈希值的令牌。同时,由于哈希值“掩盖”了各种原始信息,因此也就保证了密钥不会被攻击者所发现。

注:将私有数据添加到哈希之中的过程,被称为加盐(salting),这使得破解令牌几乎是不可能的。

身份验证过程

至此,想必您已经理解了令牌的创建过程。那么,我们又该如何用它来验证用户的API呢?

登录

在用户登录时,系统会生成一个令牌,并将其与用户模型(model)一起存储在数据库中。

  1. logincontrol.js: 
  2. if (passwordCorrect) { 
  3.   user.token = generateToken(user.id); 
  4.   user.save(); 

然后作为对于登录请求的响应,该令牌被添加到authorization的头部。

logincontrol.js:

  1. if (passwordCorrect) { 
  2.   user.token = generateToken(user.id); 
  3.   user.save(); 
  4.   res.headers("authorization",`Bearer ${token}`).send(); 

验证请求

有了令牌,用户现在就可以将其添加到各种后续的请求中,以验明正身了。

而当服务器收到添加了身份信息的令牌请求后,会进行如下操作:

  • 对令牌进行解码,并从有效载荷中提取ID。
  • 使用此ID,在数据库中查找该用户的信息。
  • 将请求令牌与带有用户模型的存储令牌进行比较。如果匹配,则认定该用户的“合法”身份。

authMiddleware.js:

  1. const token = req.header.token; 
  2. const payload = decodeToken(token); 
  3. const user = User.findById(payload.id); 
  4. if (user.token = token) { 
  5.   // Authorized 
  6. } else { 
  7.   // Unauthorized 

注销

如果该用户要求注销,那么系统只需删除掉当前已添加到用户模型的令牌便可。由于用户手上的令牌及时失效了,因此如果他需要再次登录的话,应重新产生新的令牌。

logoutcontrol.js:

  1. user.token = null
  2. user.save(); 

总结

通过上面的逐步分析,希望您能够对于如何使用JSON Web Token来加固API,已经建立起了基本的概念。当然,该话题涵括的内容远不止这些,如果您有兴趣的话,可以通过如下链接进行扩展阅读:

  • Jwt.io - https://jwt.io/
  • 什么是JSON Web Token?- https://robmclarty.com/blog/what-is-a-json-web-token

原文标题:HowJSON WebToken (JWT) Secures YourAPI,作者:Anthony Gore

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

【编辑推荐】

  1. 简析认证加授权如何使API更安全
  2. 细说API – 认证、授权和凭证
  3. 前后端API交互如何保证数据安全性?
  4. 绕过短信双因子身份验证的六种方法
  5. 不就是个短信登录API嘛,有这么复杂吗?
【责任编辑:赵宁宁 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+兴博汇注册送38元

我的运维日志系统构建之路

我的运维日志系统构建之路

数据驱动运维
共18章 | 我叫于小炳

198人订阅学习

CentOS文件服务的最佳实战

CentOS文件服务的最佳实战

涨薪跳槽必备技能
共15章 | 追风蚂蚁

90人订阅学习

小白网工宝典

小白网工宝典

一次搞定思科华为
共15章 | 思科小牛

505人订阅学习

读 书 +兴博汇注册送38元

软件工程:实践者的研究方法

20多年以来,《软件工程:实践者的研究方法》一书是最受学生和行业专业人员欢迎的软件工程指南。它在全面而系统、概括而清晰地介绍软件工程...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO播客

博聚网