API密钥与JWT授权对比详解

译文 精选
安全 应用安全
构建API时需要检查用例才能确定对应API实施的安全方案。

译者 | 张增斌

审校 | 梁策 孙淑娟

对于某些用例,API密钥就足够了。但另一些情况下,出于安全和灵活的考虑,还需要JSON Web令牌(JWT)授权。所以要比较API密钥和JWT授权两个方案,具体方案还需具体分析。

所有API调用都需要一定程度的安全性和访问控制

具有合理ACL的API密钥可以在不增加太多开销的情况下提供足够的安全性。但是,随着微服务的使用在各种大小任务中增加,API生态系统可能会需要像JWT授权方案这样更统一、更细粒度、更安全的方案。

适合API密钥的情况

对使用基于云的搜索API的在线企业来说,只要数据的基础索引不包含任何机密信息,通常可以公开只读API密钥,而不会带来很大风险。

事实上,出于性能考虑,客户端应用程序应该直接连接到云搜索引擎,从而公开其API密钥——以避免在进入云之前更长时间地访问后端服务器。 另一方面,索引更新需要限制对API密钥的访问,而这些API密钥不应被公开。

在这两个用例(搜索和索引)中,API密钥通常都很不错,无需在JWT 授权上耗费金钱。

何时该考虑JWT授权

API需要越来越灵活,也越来越需要保护。

JWT授权不仅额外提高了安全级别(详见下文),还提供了一种更易于管理、更简单的方法来协调日常中使用大量的API网络。

JWT通过生成包含用户和应用程序级别信息(加密或散列)的单个共享令牌来集中身份验证和授权,以帮助同一生态系统中的所有API确定允许令牌 持有者执行的操作。

乍一看,API的密钥似乎很简单,你只需要发送正确的API密钥,就可以开始使用,但这好得有点不真实。

当生态系统依赖于许多集成的微服务时,大量API密钥管理将会变得混乱、不可靠甚至几乎无法进行。

它们会有数量增加、更改、过期、被删除、ACL更改等等情况,而不通知依赖这些相同API密钥的应用程序和用户。

使用JWT可为单点登录架构奠定基础,下文将详述这一点。

使用API密钥与JWT授权

使用API密钥

API密钥直接、简单且完全透明。它们不代表任何基础信息,不加密秘密消息,只是不可读的唯一ID。

下面是一个在客户端javascript中公开可用的API密钥的示例:

该代码包括一个App ID(app-id-BBRSSHR),它使用API密钥(temp-search-key-ere452sdaz56qsjh565d)进行搜索。

App ID 是指一个面向用户的应用程序(如在线网站或流媒体服务)。API 密钥是临时的,它在一段时间后就过期,从而具有一定保护作用,能防止不必要的使用或滥用。

import { hitTemplate } from "./helpers";
const search = instantsearch({
appId: "app-id-BBRSSHR",
apiKey: "temp-search-key-ere452sdaz56qsjh565d",
indexName: "demo_ecommerce"
});

另一个例子是索引,它需要一个更安全的API密钥。它有相同的格式(appId+apiKey),但其秘钥要么在编译代码中,要么在后端的安全数据库中,因而对公众隐藏且为私有。

App ID (YourApplicationID) 是指后台系统。 API 密钥 (YourAdminAPIKey) 可以是一个永久的管理密钥,每年只更改一次以简化维护。

use Algolia\AlgoliaSearch\SearchClient;
$client = SearchClient::create(
'YourApplicationID',
'YourAdminAPIKey'
);
$index = $client->initIndex('demo_ecommerce');
$index->saveObject(
[
'firstname' => 'Jimmie',
'lastname' => 'Barninger',
'city' => 'New York',
'objectID' => 'myID'
]
);

使用 JWT 令牌

JWT令牌是一大串不可读的字符,其中包含的信息已隐藏和编码,被签名或加密算法覆盖。它由三部分组成:头部(header)、主体(body)和签名(signature),

由句点分隔:Header.Body.Signature。

EZPZAAdsqfqfzeezarEUARLEA.sqfdqsTIYfddhtreujhgGSFJ.fkdlsqEgfdsgkerGAFSLEvdslmgIegeVDEzefsqd

EZPZAADSQFZEEZAREUARLEA是JWT头,其中包含以下信息:

{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}

我们有不同的算法可用,例如 RS256 和 HS256。 这里我们使用 HS256算法,它需要在生成签名时使用私钥,RS256则使用私钥和公钥组合。

sqfdqsTIYfddhtreujhgGSFJ是 JWT 主体(称为有效负载),其中包含用户的身份,以帮助确立令牌用户的权利。 它还提供过期日期(越短越安全)等其他信息。

{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}

fkdlsqEgfdsgkerGAFSLEvdslmgIegeVDEzefsqd是JWT签名 ,它如头部所示,通过使用 HS256 散列方法组合头部、主体和共享私钥组合生成。

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

这样你就得到了相应的令牌:Header.Body.Signature:

EZPZAAdsqfqfzeezarEUARLEA.sqfdqsTIYfddhtreujhgGSFJ.fkdlsqEgfdsgkerGAFSLEvdslmgIegeVDEzefsqd

关于身份验证(Authentication)和授权(Authorization)

API密钥和JWT都用于身份验证和授权,但方式有所不同。

  • 身份验证(Authentication)允许用户或应用程序使用API的一种或多种方法。
  • 授权(Authorization)则规定了用户或应用程序如何使用这些方法。一些应用程序或用户只能读取数据,一些可以更新,一些则是管理员(角色和权限)。API密钥也是如此,由它们的ACL管理,它们可以是只读、写访问或管理。

进行身份验证和授权时,API密钥使用相同的API密钥,JWT授权则需要在生成授权令牌之前进行初始身份验证。

一旦生成了令牌,它就可以在整个生态系统中使用,以确定令牌持有者能做什么和不能做什么。

此外,API密钥验证的是应用程序而不是用户;而JWT同时对用户和应用程序进行身份验证。当然,你可以使用API密钥进行用户级授权,但它的设计并不完善——生态系统需要为每个用户或会话id生成和管理API密钥,这对系统来说是不必要的负担。

保护和安全提升

在安全方面,API密钥和JWT都容易受到攻击。最好的安全措施是为所有端到端通信实施安全架构。

不过,因为它们需要被隐藏,API密钥在历史上不太安全。

你可以使用SSL/TLS/HTTPS隐藏密钥,或者将密钥的使用限制在后端进程。但是,你不能控制所有API的使用,且API密钥也可能会泄漏,同时HTTPS也并不总是可行方案等等。

在JWT中,由于令牌是散列/加密的,因此它具有更安全的方法,不太可能被公开。

JWT令牌中包含哪些信息?

API密钥和JWT令牌之间最显著的区别在于,JWT令牌是自包含的:它们包含API保护交易和确定令牌持有人权利粒度所需的信息。

相反,API密钥使用其唯一性来获得初始访问;但是,API需要在中央表中找到与密钥关联的ACL,以精准确定密钥允许访问的内容。

通常,API密钥只保障应用程序层级的安全,为每个用户提供相同的访问权限;而JWT令牌提供用户级访问。

JWT令牌可以包含过期日期和用户标识符等信息,以确定用户在整个生态系统中的权限。

让我们看一下JWT令牌中可以包含的一些信息:

  • iss(颁发者):标识发布 JWT 的主体。
  • sub(主题):标识作为 JWT 主题的主体, 必须是唯一的。
  • aud(受众):标识 JWT 的目标接收者(字符串数组/uri)。
  • exp(过期时间):标识过期时间(UTC Unix),在此之后你必须不再接受此令牌。 它应该在发布时间之后。
  • nbf(not before):标识不能接受 JWT 的 UTC Unix 时间
  • iat(发布时间):标识发布 JWT 的 UTC Unix 时间。
  • jti(JWT ID):为 JWT 提供唯一标识符。

例子:

{
"iss": "stackoverflow",
"sub": "joe",
"aud": ["all"],
"iat": 1300819370,
"exp": 1300819380,
"jti": "3F2504E0-4F89-11D3-9A0C-0305E82C3301",
"context":
{
"user":
{
"key": "joe",
"displayName": "Joe Smith"
},
"roles":["admin","finaluser"]
}
}

JWT授权具有灵活性、可靠性和更高的安全性

下面是一个使用场景:

  • 你有多种应用程序,这些程序可能:
  • 允许我们跟踪所有用户API使用情况;
  • 允许访问账单和客户数据;
  • 允许API用户更改在不同系统上设置;
  • 检索产品数据或业务内容等。

使用API密钥操作

当有很多的API在运行时,就会出现问题。这些访问所需的 100 多个 API 密钥要存储在哪里呢?管理过多的API密钥需要为生态系统中运行的所有应用程序提供一个API密钥表。

因此,生态系统中的每个应用程序都必须了解数据库,都需要连接并读取该密钥表。此外,一些应用程序将被允许生成新密钥或修改现有密钥。

所有这些都是不错的方式,但很难维护。管理这问题的一种方法是创建一个API,API根据该数据库来验证密钥。但为此你需要第二个身份验证系统来连接到这个API。

不仅检索API密钥很繁琐,维护其持续时间和授权级别也是冗长的过程,而且并不是每个应用程序都在应用程序级别运行,它们需要用户级别的权限。

此外,API的使用方式因系统而异。更糟糕的是,不同的应用程序共享API密钥,因此要依赖不同的应用程序来维护对共享API密钥的正确访问级别。

切换到JWT

任何需要身份验证的API都可以轻松切换到JWT的授权。通过JWT授权,你可以获得基于用户的身份验证。一旦用户通过身份验证,用户就会获得一个可以在所有系统上使用的安全令牌。

用户(以及令牌)采用集中方式的管理。你设置访问权限,并为每个系统赋予每个用户不同的权限。JWT授权端点对用户进行身份验证并创建令牌。

使用这种架构,下一步就是在整个生态系统中创建一个单点的登录,并只依赖令牌来获得权限。

最后,最简单、最稳健、最易管理的方法是创建一个专门用于身份验证和授权的单一端点,这样整个生态系统中的所有其他服务器都可以依赖该中心点来授权客户端和服务器之间的API交互。

总之,有时JWT是绝对必要的,有时则是“过犹不及”

作为一名应用程序开发人员,我在构建API时主要关心它们是否得到了正确的使用,并提供了正确的数据和功能。

因此,我在很大程度上遵从DevOps的想法来推荐最佳和最易管理的安全措施。

但是,除了安全之外还有其他问题需要关注。在一个大型的生态系统中,我们需要一种简单而稳健的方式来跨多个系统和服务器访问微服务,而这最好通过集中身份验证和授权过程来实现。

在以下两种情况下,选用JWT显得有些“过犹不及”:

  • 一个只有几个API的简单生态系统。
  • 第三方API的供应商。

第三方API一般易于使用和快速实现,集成时只需要很少的前期工作。

此外,你需要共享用于签名令牌的密钥。所以最好控制两端,而这在第三方场景中是不可能的,并且你还需要信任实现。例如,API可以选择忽略过期日期或有效起始日期(“not before”)。

不过,JWT 在以下情况就很有必要了:

  • 当多个服务需要在一个庞大的网络上相互通信时,你需要使用JWT。
  • 当不仅仅是应用程序,而是每个网络或应用程序都需要基于用户的不同访问级别时,集中和保护这些交易所至关重要。
  • 控制流量并能够对网络呼叫进行优先级排序也很关键。在添加新的或改进现有服务时最好能获得简单的即插即用体验。

译者介绍

张增斌,51CTO社区编辑,多年的安全攻防从业经验,主要研究方向:安全开发、逆向破解、漏洞挖掘、黑灰产攻防对抗。目前主要从事游戏安全的研究。本人独立运营《小道安全》公众号。

原文标题:How API Keys Compare to JWT Authorization: A Detailed Overview,作者:Algolia


责任编辑:华轩 来源: 51CTO
相关推荐

2009-11-04 10:50:48

Oracle创建用户授

2014-12-22 10:28:47

2018-05-04 14:34:06

微服务SOAAPI

2010-11-18 11:08:30

oracle授权语句

2021-07-16 06:56:50

授权机制Session

2022-04-06 07:50:57

JWT后端Spring

2019-03-27 15:51:51

API 认证授权

2009-06-17 16:12:26

java电子书制作软件

2012-07-31 10:37:20

微软Windows8

2011-11-14 16:07:22

2019-12-30 09:00:00

Web 开发代码

2024-03-20 10:53:15

2010-03-29 10:19:24

2011-12-07 14:57:44

JavaNIO

2009-06-16 09:41:00

2009-06-16 10:10:40

JavaMail AP

2022-02-24 08:00:00

API混合云数据

2022-05-25 09:00:00

令牌JWT安全

2024-04-07 10:07:52

2019-05-10 09:00:00

JWTAPI身份验证
点赞
收藏

51CTO技术栈公众号