当前位置: 首页 > 科技观察

APIKeyvs.JWT授权详解

时间:2023-03-13 17:08:24 科技观察

译者|张增斌评论|LiangCeSunShujuan对于某些用例,API密钥就足够了。但在其他情况下,为了安全性和灵活性,还需要JSONWebToken(JWT)授权。因此,比较APIkey和JWT授权这两种方案,需要具体具体的方案具体分析。所有API调用都需要一定程度的安全性和访问控制。具有合理ACL的API密钥可以在不增加太多开销的情况下提供足够的安全性。然而,随着大大小小的任务对微服务的使用增加,API生态系统可能需要更统一、更细粒度和更安全的解决方案,如JWT授权方案。何时使用API密钥对于使用基于云的搜索API的在线业务,只要数据的基础索引不包含任何机密信息,通常可以在没有重大风险的情况下披露只读API密钥。事实上,出于性能原因,客户端应用程序应该直接连接到云搜索引擎,从而暴露其API密钥——以避免在进入云之前更长时间地访问后端服务器。另一方面,索引更新需要限制访问API密钥,不应公开这些密钥。在这两种用例(搜索和索引)中,API密钥通常都可以,无需花钱购买JWT授权。何时考虑JWT授权API需要更灵活、更安全。JWT授权不仅提供了额外的安全级别(见下文),还提供了一种更易于管理和更简单的方式来协调日常生活中使用的大量API网络。JWT通过生成包含用户和应用程序级信息(加密或散列)的单个共享令牌来集中身份验证和授权,以帮助同一生态系统中的所有API确定允许令牌持有者执行的操作。APIkey乍看之下很简单,只需要发送正确的APIkey,就可以开始使用了,但这好得令人难以置信。当一个生态系统依赖于许多集成微服务时,管理大量API密钥可能会变得混乱、不可靠,甚至几乎不可能。它们可以增加数量、更改、过期、删除、ACL更改等,而无需通知依赖这些相同API密钥的应用程序和用户。使用JWT为单点登录架构提供了基础,下面将对此进行详细介绍。使用APIKeys和JWT授权使用APIKeys和APIKeys是直接、简单且完全透明的。它们不代表任何底层信息,不加密秘密消息,只是不可读的唯一ID。以下是客户端javascript中公开可用的API密钥的示例:该代码包含一个AppID(app-id-BBRSSHR),它使用API密钥(temp-search-key-ere452sdaz56qsjh565d)进行搜索。AppID是指面向用户的应用程序(例如在线网站或流媒体服务)。API密钥是临时的,会在一段时间后过期,从而提供一些保护以防止不必要的使用或滥用。从“./helpers”导入{hitTemplate};constsearch=instantsearch({appId:"app-id-BBRSSHR",apiKey:"temp-search-key-ere452sdaz56qsjh565d",indexName:"demo_ecommerce"});另一个例子是索引,它需要更安全的API密钥。它具有相同的格式(appId+apiKey),但它的密钥要么在编译代码中,要么在后端的安全数据库中,因此对公众隐藏并保密。AppID(YourApplicationID)指的是后台系统。API密钥(YourAdminAPIKey)可以是永久管理密钥,每年仅更改一次以简化维护。使用Algolia\AlgoliaSearch\SearchClient;$client=SearchClient::create('YourApplicationID','YourAdminAPIKey');$index=$client->initIndex('demo_ecommerce');$index->??saveObject(['firstname'=>'Jimmie','lastname'=>'Barninger','city'=>'NewYork','objectID'=>'myID']);使用JWT令牌JWT令牌是一大串不可读的字符,其中包含已被隐藏和编码、被签名或加密算法覆盖的信息。它由三部分组成:header、body、signature,用句点分隔:Header.Body.Signature。EZPZAAdsqfqfzeezarEUARLEA.sqfdqsTIYfddhtreujhgGSFJ.fkdlsqEgfdsgkerGAFSLEvdslmgIegeVDEzefsqdEZPZAADSQFZEEZAREUARLEA是JWT头,其中包含以下信息:{"alg":"HS256","typ":"JWT"}{"sub":"1234567890","name":"JohnDoe","iat":1516239022}我们有不同的可用算法,例如RS256和HS256。这里我们使用的是HS256算法,在生成签名的时候需要私钥,而RS256使用的是私钥和公钥的组合。sqfdqsTIYfddhtreujhgGSFJ是JWT主体(称为负载),其中包含用户身份以帮助建立令牌用户的权利。它还提供其他信息,如有效期(越短越安全)。{"sub":"1234567890","name":"JohnDoe","iat":1516239022}fkdlsqEgfdsgkerGAFSLEvdslmgIegeVDEzefsqd是JWT签名,如标头所示,通过使用HS256哈希组合标头、正文和共享私钥方法组合键生成。HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)这样你就得到了相应的令牌:Header.Body.Signature:EZPZAAdsqfqfzeezarEUARLEA.sqfdqsTIYfddhtreujhgGSFJ.fkdlsqEgfdsgkerGAFSLEvdslmgIegeVDEzefsqd关于身份验证(Authentication)和授权(Authorization)API密钥和JWT都用于身份验证和授权,但方式不同。身份验证(Authentication)允许用户或应用程序使用API的一种或多种方法。授权指定用户或应用程序如何使用这些方法。有些应用程序或用户只能读取数据,有些可以更新,有些是管理员(角色和权限)。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(subject):标识主题为JWT的主题,必须是唯一的。aud(audience):标识JWT的预期接收者(字符串/uri数组)。exp(过期时间):标识过期时间(UTCUnix),之后您不得再接受此令牌。应该是在发布时间之后。nbf(notbefore):标识不能接受JWT时的UTCUnix时间iat(publishedtime):标识JWT发布时的UTCUnix时间。jti(JWTID):为JWT提供唯一标识符。示例:{“iss”:“stackoverflow”,“sub”:“joe”,“aud”:[“all”],“iat”:1300819370,“exp”:1300819380,“jti”:“3F2504E0-4F89-11D3-9A0C-0305E82C3301","context":{"user":{"key":"joe","displayName":"JoeSmith"},"roles":["admin","finaluser"]}}JWT授权的灵活性、可靠性和更高的安全性下面是一个使用场景:您有多个应用程序,这些应用程序可能:允许我们跟踪所有用户API使用情况;允许访问账单和客户数据;允许API用户更改不同系统上的设置;检索产品数据或业务内容等。使用API密钥当有许多API正在运行时,可能会出现问题。这些访问所需的100多个API密钥存储在哪里?管理过多的API密钥需要为生态系统中运行的所有应用程序提供一个API密钥表。所以生态系统中的每个应用程序都必须了解数据库,需要连接并读取该密钥表。此外,一些应用程序将被允许生成新密钥或修改现有密钥。所有这些都是很好的方法,但很难维护。管理此问题的一种方法是创建一个API,用于根据该数据库验证密钥。但是为此,您需要第二个身份验证系统来连接到此API。不仅检索API密钥繁琐,维护其持续时间和授权级别也是一个漫长的过程,而且并非每个应用程序都在应用程序级别运行,它们需要用户级别的权限。此外,API的使用方式因系统而异。更糟糕的是,不同的应用程序共享API密钥,因此依赖于不同的应用程序来维持对共享API密钥的正确访问级别。切换到JWT任何需要身份验证的API都可以轻松切换到JWT进行授权。通过JWT授权,您可以获得基于用户的身份验证。一旦用户通过身份验证,就会为用户提供一个可以在所有系统中使用的安全令牌。用户(和代币)以集中方式管理。您设置访问权限,并为每个系统赋予每个用户不同的权限。JWT授权端点对用户进行身份验证并创建令牌。使用此架构,下一步是创建跨生态系统的单点登录,并且仅依赖令牌获取权限。最后,最简单、最健壮和最易于管理的方法是创建一个专门用于身份验证和授权的单一端点,以便整个生态系统中的所有其他服务器都可以依赖这个中心点来授权客户端和服务器之间的连接API交互.总而言之,有时JWT是绝对必要的,有时它们“太多了”作为应用程序开发人员,我在构建API时主要关心的是它们是否被正确使用并提供正确的数据和功能。因此,我主要遵循DevOps思想来推荐最佳和最易于管理的安全措施。然而,除了安全之外,还有其他问题。在大型生态系统中,我们需要一种简单而健壮的方式来跨多个系统和服务器访问微服务,而这最好通过集中身份验证和授权过程来实现。在以下两种情况下,JWT的选择有点“太多”:一个简单的生态系统,只有几个API。第三方API的提供者。第三方API通常易于使用和快速实施,在集成时需要很少的前期工作。此外,您需要共享用于签署令牌的密钥。所以最好控制两端,这在3rd方场景中是不可能的,而且你还需要信任实现。例如,API可能会选择忽略到期日期或有效起始日期(“不早于”)。但是在以下情况下JWT是必须的:当多个服务需要在大型网络上相互通信时,就需要使用JWT。当不仅应用程序而且每个网络或应用程序都需要基于用户的不同级别的访问时,集中和保护这些交换是至关重要的。控制流量和能够确定网络呼叫的优先级也是关键。添加新服务或改进现有服务时,最好有简单的即插即用体验。译者介绍社区编辑张增斌,拥有多年安全攻防行业从业经验。主要研究方向为:安全开发、逆向破解、漏洞挖掘、黑灰产攻防对抗。目前主要从事游戏安全研究。我独立运行《小道安全》公众号。原标题:HowAPIKeysComparetoJWTAuthorization:ADetailedOverview,作者:Algolia