我正在使用Auth0作为身份验证服务设置REST API。一切都在发挥作用,但在一个相当奇怪的事件发生后,我的信心有点动摇了。
我的实施基于示例代码here(RS256部分)和here。唯一的修改是我将PublicKey
转换为RSAPublicKey
。
问题在于我想肯定验证会在签名错误时失败。我更改了签名的最后一个字符(我们将说“x”)并且令牌仍然经过验证。 但是 - 将其切换为除“x”以外的任何字符或原始生成的字符导致其按预期失败。
我的怀疑是,这是由于某种填充/编码/解码/ Base64问题,而我碰巧选择了一个具有相同的前n个位数的字符?当然,这意味着如果要做出成功的“猜测”,它将需要包括令牌的剩余四十亿字符 - 这是它存在的全部要点。所以我并不担心令牌是可猜测的 - 我只是确保我已经正确地实现了验证的要点。
import com.auth0.jwk.Jwk;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.security.interfaces.RSAPublicKey;
public class Application {
public static void main(String[] args) {
try {
JwkProvider provider = new UrlJwkProvider("<my-provider>");
Jwk jwk = provider.get("<my-key-id>");
String token = "<some-token-passed-from-client>";
RSAPublicKey publicKey = (RSAPublicKey) jwk.getPublicKey();
Algorithm algorithm = Algorithm.RSA256(publicKey, null);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("<my-issuer>")
.build();
DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException exception) {
System.out.println("JWT Exception: " + exception.getMessage());
} catch (JwkException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
除了stackoverflow.com/a/2946880/1187415(下面的截图)之外,别无其他。
令牌包含3个单独的颜色部分:
尤其是标头没有签名,它们几乎可以包含任何内容并且可以更改。尽管如果令牌丢失,令牌将无法解码(例如错误的算法值)。
有将所有这些数据一起编码,填充和序列化的规则,请参考规范。可以在令牌中添加/删除/编辑几个字节,并且仍然具有有效的令牌,尽管略有不同(修改的填充或标头)。但是,不可能更改令牌的有效负载,这很重要。
JWT库提供了单独的功能来从令牌中提取信息,例如%2$@
和cargo build --release
,避免了任何潜在的混乱。假设如果不小心从标题而不是有效内容中读取用户标识符,那将是一个关键漏洞,因为可以自由更改。