我知道它们必须是安全的,但我真的很想了解这些技术。我错过了什么?
JWT可以签名、加密或同时使用。如果一个令牌只被签名,未被加密,所有人都能读取其内容,但是当你不知道私钥时,你无法更改它。否则,接收方会注意到签名不再匹配。
回答您的评论:我不确定我是否正确理解了您的评论。为了确保:您是否了解数字签名?我将简要介绍一种变体(HMAC,它是对称的,但还有许多其他变体)。
假设Alice想向Bob发送JWT。他们都知道一些共享秘密。Mallory不知道那个秘密,但想干扰并更改JWT。为了防止这种情况发生,Alice计算 Hash(payload + secret)
并将其作为签名附加在后面。
接收消息时,Bob也可以计算 Hash(payload + secret)
来检查签名是否匹配。
然而,如果Mallory更改了内容,她就不能计算匹配的签名(它应该是Hash(newContent + secret)
)。她不知道秘密,也没有办法找到它。这意味着如果她更改了什么,签名就不再匹配了,Bob将不再接受JWT。
假设我向另一个人发送消息{"id":1}
并用Hash(content + secret)
进行签名。 (+在这里只是连接)。我使用SHA256哈希函数,得到的签名为:330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c
。现在轮到你了:扮演Mallory的角色,尝试对消息{"id":2}
进行签名。你不能因为你不知道我使用了哪个秘密。如果我假设接收方知道秘密,他可以计算任何消息的签名并检查是否正确。
jwt.io
,将你的令牌粘贴进去并阅读内容。这对许多人来说最初是令人不安的。JSON Web Token(JWT)中的内容本质上并不安全,但是有一个内置功能来验证令牌的真实性。JWT由三个哈希值组成,用句点分隔。第三部分是签名。在公钥/私钥系统中,发布者使用私钥对令牌签名,只有相应的公钥才能进行验证。
重要的是要理解发布者和验证者之间的区别。令牌的接收方有责任进行验证。
在Web应用程序中安全地使用JWT有两个关键步骤:1)通过加密通道发送它们,2)立即在接收到令牌时验证签名。公钥加密的非对称特性使得JWT签名验证成为可能。公钥可以验证JWT是否被其相应的私钥签名。没有其他密钥组合可以进行此验证,从而防止冒充尝试。遵循这两个步骤,我们可以以数学确定性保证JWT的真实性。
更多阅读:公钥如何验证签名?
我将用一个例子来解释这个概念。
假设我向您借了10美元,然后我给了您一张带有我的签名的 IOU(即欠条)。当您或其他人把这张 IOU 带回给我时,我就会还钱,并检查签名以确保它是我的。
我无法确保您不会向任何人展示此 IOU 的内容,甚至将其交给第三方,我所关心的只是这张 IOU 是否由我签名,当有人向我出示这张 IOU 并要求付款时。
JWT 的工作方式与此类似,服务器只能确保接收到的令牌是由其自己颁发的。
您需要采取其他措施来保护其安全性,例如使用 HTTPS 进行传输加密,确保存储令牌的本地存储处于安全状态,并设置来源。
需要注意的是,JWT 用于授权而非认证。
因此,只有在服务器通过指定凭据对您进行身份验证后,才会为您创建 JWT。一旦为所有未来与服务器的交互创建了 JWT,就可以使用 JWT。因此,JWT 告诉服务器该用户已经过身份验证,如果他具有该角色,则让他访问特定资源。
JWT 负载中的信息对每个人都可见。可能存在“中间人”攻击并更改 JWT 的内容。因此,我们不应在负载中传递任何敏感信息,如密码。如果希望使其更加安全,可以加密负载数据。如果负载被篡改,服务器将识别它。
因此,假设用户已通过身份验证并获得了 JWT。生成的 JWT 具有指定 管理员 角色的声明。此外,签名是使用以下方式生成的:
现在,此 JWT 已被篡改,假设角色已更改为 超级管理员。
然后,当服务器接收此令牌时,它将再次使用密钥(仅服务器拥有)和负载生成签名。这将不匹配 JWT 中的签名。因此,服务器将知道 JWT 已被篡改。
JWT
不被视为身份验证
令牌?
它具有包含用户信息的有效负载。头部
,有效负载
和密钥
用于“验证”原始签名(最初由身份验证服务器生成),这意味着如果有效负载中有任何更改,则用户被认为不是原始用户,因此不是真实的。难道这不简化了身份验证过程吗?也就是说,使用令牌,我们可以在每个请求中对用户进行身份验证,而无需再次访问身份验证服务器,然后根据用户角色允许访问资源。 - mabiyan我不是密码学专家,所以(希望)我的答案能帮到那些也不是专家的人。
在编程中,使用密码学有两种可能的方式:
当我们想要确保数据来自可信源时,我们使用签名。 当我们想要保护数据时,我们使用加密。
签名/验证使用非对称算法,即我们使用一个密钥(私钥)进行签名,数据接收者使用另一个密钥(公钥)进行验证。
对称算法使用相同的密钥来加密和解密数据。
加密可以使用对称算法和非对称算法进行。关于这个主题的相对简单的文章
上述是常识,以下是我的观点。
当JWT用于简单的客户端到服务器的身份验证时,不需要签名或非对称加密。JWT可以使用快速且超安全的AES进行加密。如果服务器能解密它,说明服务器就是加密它的那一方。
总结:未经加密的JWT不安全。在没有第三方参与的情况下,可以使用对称加密代替签名。
密码 | JsonWebtoken | |
---|---|---|
有效期 | 直到密码被更改或强制更改,例如90天后。 | 只有短暂的时间,通常为1-24小时。然后需要刷新JWT。 |
重置 | 用户需要手动重置密码。 | 如果“客户端”,例如您的手机拥有JWT,则可以自动刷新。用户看不到这一过程。 |
安全性 | 每当JWT被刷新时,后端都会参与其中。JWT随时可能被撤销。 | |
更高的安全性 | “客户端”,例如其IP地址或移动设备ID(很难伪造)可以编码到JWT中。任何对此的篡改都可以在后端轻松检测到。 |
md5('original messaged' + secret) != md5('changed message' + secret)
,因此如果有人更改了消息,您可以检测到它。 - Pithikos