如果我有一个JWT,我可以解码有效载荷,这是安全的吗?难道我不能从报头中获取令牌,解码并更改有效负载中的用户信息,然后用相同的正确编码的秘密将其发送回来吗?

我知道它们一定很安全,但我真的很想了解这些技术。我错过了什么?


jwt既可以签名,也可以加密,或者两者都可以。如果一个令牌经过签名,但没有加密,那么每个人都可以读取它的内容,但是当您不知道私钥时,就不能更改它。否则,接收方将注意到签名不再匹配。

回答你的评论:我不确定我是否正确理解了你的评论。只是为了确定:你知道并理解数字签名吗?我将简单地解释一种变体(HMAC,它是对称的,但还有许多其他变体)。

让我们假设Alice想要发送一个JWT给Bob。他们都知道一些共同的秘密。马洛里不知道这个秘密,但想要干涉和改变JWT。为了防止这种情况,Alice计算Hash(payload + secret)并将其作为签名追加。

当收到消息时,Bob还可以计算Hash(payload + secret)来检查签名是否匹配。 但是,如果Mallory更改了内容中的某些内容,她就无法计算匹配的签名(即Hash(newContent + secret))。她不知道这个秘密,也没有办法知道。 这意味着如果她更改了某些内容,签名将不再匹配,Bob将不再接受JWT。

Let's suppose, I send another person the message {"id":1} and sign it with Hash(content + secret). (+ is just concatenation here). I use the SHA256 Hash function, and the signature I get is: 330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c. Now it's your turn: play the role of Mallory and try to sign the message {"id":2}. You can't because you don't know which secret I used. If I suppose that the recipient knows the secret, he CAN calculate the signature of any message and check if it's correct.

你可以去jwt。Io,粘贴您的令牌并读取内容。一开始,这对很多人来说是不和谐的。

简而言之,智威汤逊并不关心加密问题。它关心验证。也就是说,它总是可以得到“这个令牌的内容是否已被操纵”的答案?这意味着用户对JWT令牌的操作是无效的,因为服务器将知道并忽略令牌。服务器在向客户端发出令牌时根据有效负载添加签名。随后,它验证有效载荷和匹配签名。

合乎逻辑的问题是,它不关心加密内容的动机是什么?

The simplest reason is because it assumes this is a solved problem for the most part. If dealing with a client like the web browser for example, you can store the JWT tokens in a cookie that is secure (is not transmitted via HTTP, only via HTTPS) and httpOnly (can't be read by Javascript) and talks to the server over an encrypted channel (HTTPS). Once you know you have a secure channel between the server and client you can securely exchange JWT or whatever else you want. This keeps thing simple. A simple implementation makes adoption easier but it also lets each layer do what it does best (let HTTPS handle encryption). JWT isn't meant to store sensitive data. Once the server receives the JWT token and validates it, it is free to lookup the user ID in its own database for additional information for that user (like permissions, postal address, etc). This keeps JWT small in size and avoids inadvertent information leakage because everyone knows not to keep sensitive data in JWT.

这与cookie本身的工作方式没有太大区别。cookie通常包含未加密的有效载荷。如果你使用的是HTTPS,那么一切都很好。如果不是,建议对敏感cookie本身进行加密。如果不这样做,就可能会受到中间人攻击——代理服务器或ISP读取cookie,然后假装是你,重新播放它们。出于类似的原因,JWT应该始终通过HTTPS之类的安全层进行交换。

json web令牌(JWT)中的内容本质上并不安全,但有一个内置的功能用于验证令牌的真实性。JWT是用句点分隔的三个散列。第三个是签名。在公钥/私钥系统中,颁发者使用私钥签署令牌签名,该私钥只能由其对应的公钥验证。

理解发布者和验证者之间的区别是很重要的。令牌的接收者负责验证它。

There are two critical steps in using JWT securely in a web application: 1) send them over an encrypted channel, and 2) verify the signature immediately upon receiving it. The asymmetric nature of public key cryptography makes JWT signature verification possible. A public key verifies a JWT was signed by its matching private key. No other combination of keys can do this verification, thus preventing impersonation attempts. Follow these two steps and we can guarantee with mathematical certainty the authenticity of a JWT.

更多阅读:公钥如何验证签名?

只有服务器上的JWT的privateKey才能解密加密的JWT。那些知道privateKey的人将能够解密加密的JWT。

将私钥隐藏在服务器的安全位置,并且永远不要告诉任何人私钥。

让我们从头开始讨论:

JWT is a very modern, simple and secure approach which extends for Json Web Tokens. Json Web Tokens are a stateless solution for authentication. So there is no need to store any session state on the server, which of course is perfect for restful APIs. Restful APIs should always be stateless, and the most widely used alternative to authentication with JWTs is to just store the user's log-in state on the server using sessions. But then of course does not follow the principle that says that restful APIs should be stateless and that's why solutions like JWT became popular and effective.

现在让我们来了解一下Json Web Tokens的身份验证是如何工作的。假设我们的数据库中已经有一个注册用户。因此,用户的客户端首先发出带有用户名和密码的post请求,然后应用程序检查用户是否存在,如果密码正确,那么应用程序将仅为该用户生成一个唯一的Json Web Token。

令牌是使用存储在服务器上的秘密字符串创建的。接下来,服务器将JWT发送回客户端,客户端将其存储在cookie或本地存储中。

就像这样,用户通过身份验证并登录到我们的应用程序,而不会在服务器上留下任何状态。

所以服务器实际上不知道哪个用户实际登录了,但当然,用户知道他已经登录了,因为他有一个有效的Json Web Token,这有点像护照,可以访问应用程序的受保护部分。

再一次,为了确保你们理解了。一个用户一旦得到他唯一有效的Json Web令牌就登录了,这个令牌没有保存在服务器上的任何地方。所以这个过程是完全无状态的。

然后,每次用户想要访问一个受保护的路由,例如他的用户配置文件数据。他将他的Json Web Token与请求一起发送,所以这有点像出示他的护照来访问那条路线。

一旦请求到达服务器,我们的应用程序将验证Json Web令牌是否有效,如果用户确实是他所说的那个人,那么请求的数据将被发送到客户端,如果不是,那么将会有一个错误告诉用户他不允许访问该资源。

所有这些通信都必须通过https进行,所以安全加密的Http,以防止任何人可以访问密码或Json Web令牌。只有这样我们才有一个真正安全的系统。

So a Json Web Token looks like left part of this screenshot which was taken from the JWT debugger at jwt.io. So essentially, it's an encoding string made up of three parts. The header, the payload and the signature Now the header is just some metadata about the token itself and the payload is the data that we can encode into the token, any data really that we want. So the more data we want to encode here the bigger the JWT. Anyway, these two parts are just plain text that will get encoded, but not encrypted.

所以任何人都可以解码并阅读它们,我们不能在这里存储任何敏感数据。但这根本不是问题,因为在第三部分,在签名部分,才是真正有趣的地方。签名是使用头、有效负载和保存在服务器上的秘密创建的。

这整个过程被称为签署Json Web令牌。签名算法使用报头、有效负载和秘密来创建唯一的签名。所以只有这个数据加上这个秘密才能创建这个签名,对吧? 然后加上头部和有效载荷,这些签名形成了JWT, 然后被发送到客户端。

一旦服务器接收到JWT以授予对受保护路由的访问权,它就需要验证它,以确定用户是否真的是他所声称的那个人。换句话说,它将验证是否没有人更改标记的标头和有效负载数据。同样,此验证步骤将检查是否没有第三方实际更改Json Web Token的报头或有效负载。

那么,这种验证实际上是如何工作的呢?其实很简单。一旦接收到JWT,验证将使用它的头部和有效负载,以及仍然保存在服务器上的秘密,基本上创建一个测试签名。

但是JWT第一次创建时生成的原始签名仍然在令牌中,对吗?这就是验证的关键。因为现在我们所要做的就是将测试签名与原始签名进行比较。 如果测试签名与原始签名相同,则意味着有效负载和报头没有被修改。

Because if they had been modified, then the test signature would have to be different. Therefore in this case where there has been no alteration of the data, we can then authenticate the user. And of course, if the two signatures are actually different, well, then it means that someone tampered with the data. Usually by trying to change the payload. But that third party manipulating the payload does of course not have access to the secret, so they cannot sign the JWT. So the original signature will never correspond to the manipulated data. And therefore, the verification will always fail in this case. And that's the key to making this whole system work. It's the magic that makes JWT so simple, but also extremely powerful.

结构和安全性

It is important to note that JWT are used for authorization and not authentication. So a JWT will be created for you only after you have been authenticated by the server by may be specifying the credentials. Once JWT has been created for all future interactions with server JWT can be used. So JWT tells that server that this user has been authenticated, let him access the particular resource if he has the role. Information in the payload of the JWT is visible to everyone. There can be a "Man in the Middle" attack and the contents of the JWT can be changed. So we should not pass any sensitive information like passwords in the payload. We can encrypt the payload data if we want to make it more secure. If Payload is tampered with server will recognize it. So suppose a user has been authenticated and provided with a JWT. Generated JWT has a claim specifying role of Admin. Also the Signature is generated with

这个JWT现在被篡改了,假设 角色修改为超级管理员 然后,当服务器接收到这个令牌时,它将再次使用秘密密钥(只有服务器拥有)和有效负载生成签名。与签名不符 在JWT。这样服务器就知道JWT被篡改了。

我会用一个例子来解释。

假设我向你借了10美元,然后我给了你一张有我签名的借条。无论何时你或其他人把这张借条拿回来给我,我都会还你的,我会检查签名,确保那是我的。

我不能保证你不把这张借条的内容给任何人看,甚至给第三人看,我只关心这张借条是我签名的,当有人把这张借条给我看并让我支付的时候。

JWT的工作方式是完全相同的,服务器只能确保接收到的令牌是由自己发出的。

您需要其他措施来确保其安全,例如使用HTTPS传输时进行加密,确保存储令牌的本地存储是安全的,设置起源。

我不是密码学专家,因此(我希望)我的回答可以帮助那些既不是密码学专家的人。

在编程中使用密码学有两种可能的方式:

签署/验证 加密/解密

当我们希望确保数据来自可信来源时,我们使用签名。 当我们想要保护数据时,我们使用加密。

签名/验证使用非对称算法,即我们使用一个密钥(私有)进行签名,而数据接收者使用另一个(公共)密钥进行验证。

对称算法使用相同的密钥对数据进行加密和解密。

加密可以使用对称和非对称算法。 相对简单的文章主题

以上是常识,以下是我的观点。

当JWT用于简单的客户端到服务器标识时,不需要签名或非对称加密。JWT可以使用AES加密,这是快速和超级安全的。如果服务器可以解密它,这意味着服务器是加密它的人。

总结:未加密的JWT是不安全的。在没有第三方参与的情况下,可以使用对称加密来代替签名。