java.lang.IllegalArgumentException:如果指定的 JWT 是数字签名的,则必须指定签名密钥

2024-03-05

我正在寻求实施JWT在我的申请中,我正在通过参考以下内容进行一些研发:https://stormpath.com/blog/jwt-java-create-verify https://stormpath.com/blog/jwt-java-create-verify。我成功地实现了generateToken()方法,当我试图verifyToken()通过提取权利要求集。我不明白从哪里来apiKey.getSecret()是来自。您能指导我吗?

下面的代码供参考:

public class JJWTDemo {

    private static final String secret = "MySecrete";

    private static String generateToken(){
        String id = UUID.randomUUID().toString().replace("-", "");
        Date now = new Date();
        Date exp = new Date(System.currentTimeMillis() + (1000*30)); // 30 seconds

        String token = Jwts.builder()
                .setId(id)
                .setIssuedAt(now)
                .setNotBefore(now)
                .setExpiration(exp)
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();

        return token;
    }

    private static void verifyToken(String token){
        Claims claims = Jwts.parser().
                setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret()))
                .parseClaimsJws(token).getBody();
        System.out.println("----------------------------");
        System.out.println("ID: " + claims.getId());
        System.out.println("Subject: " + claims.getSubject());
        System.out.println("Issuer: " + claims.getIssuer());
        System.out.println("Expiration: " + claims.getExpiration());
    }

    public static void main(String[] args) {
        System.out.println(generateToken());
        String token = generateToken();
        verifyToken(token);
    }
}

我看到出现以下错误:

eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4N2E5NmYwNTcyN2M0ZDY0YjZmODlhNDAyOTQ2OTZiNyIsImlhdCI6MTQ4NDQ4NjYyNiwibmJmIjoxNDg0NDg2NjI2LCJleHAiOjE0ODQ0ODY2NTZ9.ycS7nLWnPpe28DM7CcQYBswOmMUhBd3wQwfZ9C-yQYs
Exception in thread "main" java.lang.IllegalArgumentException: A signing key must be specified if the specified JWT is digitally signed.
    at io.jsonwebtoken.lang.Assert.notNull(Assert.java:85)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:331)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481)
    at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541)
    at io.jsonwebtoken.jjwtfun.service.JJWTDemo.verifyToken(JJWTDemo.java:31)
    at io.jsonwebtoken.jjwtfun.service.JJWTDemo.main(JJWTDemo.java:41)

Maven 依赖:

<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jjwt.version}</version>
        </dependency>
<jjwt.version>0.7.0</jjwt.version>

apiKey.getSecret()博客文章中引用了分配给 Stormpath 为每个客户提供的 API 密钥的安全、随机生成和 Base64 编码的密钥(如密码)。 Stormpath 客户使用此 API 密钥对 Stormpath REST API 中的每个请求进行身份验证。由于每个 Stormpath 客户都有一个 API 密钥(并且您的应用程序可以访问该密钥),因此 API 密钥密钥是签名和验证特定于您的应用程序的 JWT 的理想“默认值”。

如果您没有 Stormpath API 密钥,任何足够强大的安全随机字节数组都可以用于签名和验证 JWT。

在上面的示例中,以下内容显示为测试密钥:

private static final String secret = "MySecrete";

这不是有效的(符合 JWT 的)密钥,并且不能用于 JWT HMAC 算法。

智威汤逊 RFCrequires那你MUST https://www.rfc-editor.org/rfc/rfc7518#section-3.2使用等于或大于哈希输出长度的字节数组密钥长度。

这意味着,如果您使用 HS256、HS384 或 HS512,则密钥字节数组必须分别为 256 位(32 字节)、384 位(48 字节)或 512 位(64 字节)。我对此进行了更详细的介绍另一个 StackOverflow 答案 https://stackoverflow.com/a/40274325/407170- 查看那里的数据,以及MacProvider可以为您生成符合规范且安全的密钥的示例。

基于此,以下是该代码示例,重写为 a) 生成有效密钥和 b) 将该密钥引用为 Base64 编码字符串:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;

import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

public class JJWTDemo {

    private static final Key secret = MacProvider.generateKey(SignatureAlgorithm.HS256);
    private static final byte[] secretBytes = secret.getEncoded();
    private static final String base64SecretBytes = Base64.getEncoder().encodeToString(secretBytes);

    private static String generateToken() {
        String id = UUID.randomUUID().toString().replace("-", "");
        Date now = new Date();
        Date exp = new Date(System.currentTimeMillis() + (1000 * 30)); // 30 seconds

        String token = Jwts.builder()
            .setId(id)
            .setIssuedAt(now)
            .setNotBefore(now)
            .setExpiration(exp)
            .signWith(SignatureAlgorithm.HS256, base64SecretBytes)
            .compact();
        
        return token;
    }

    private static void verifyToken(String token) {
        Claims claims = Jwts.parser()
            .setSigningKey(base64SecretBytes)
            .parseClaimsJws(token).getBody();
        System.out.println("----------------------------");
        System.out.println("ID: " + claims.getId());
        System.out.println("Subject: " + claims.getSubject());
        System.out.println("Issuer: " + claims.getIssuer());
        System.out.println("Expiration: " + claims.getExpiration());
    }

    public static void main(String[] args) {
        System.out.println(generateToken());
        String token = generateToken();
        verifyToken(token);
    }
}

请注意,Base64 编码的字节数组是not加密(文本编码!=加密),因此,如果您对密钥字节进行 Base64 编码,请确保您仍然保持该 Base64 字符串安全/隐藏。

最后,上面的静态最终常量(名为secret, secretBytes and base64SecretBytes)仅用于这个简单的测试演示 - 永远不要将密钥硬编码到源代码中,更不用说将它们设为静态常量,因为它们很容易被反编译。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java.lang.IllegalArgumentException:如果指定的 JWT 是数字签名的,则必须指定签名密钥 的相关文章

随机推荐

  • 解释 802.11 Wireshark 跟踪中的帧控制字节

    我有一个 Wi Fi 捕获 pcap 我正在分析并发现 802 11 规范与 Wireshark 对数据的解释之间存在不一致之处 具体来说 我想要分解的是 2 字节 802 11帧控制 field 取自http www4 ncsu edu
  • .NET Core 3.0:Razor 视图不会在更改时自动重新编译

    根据文档 https learn microsoft com en us aspnet core mvc views view compilation view aspnetcore 3 0默认情况下 Razor 视图应根据 ASP NET
  • nhibernate映射,没有主键和外键的连接

    我有这些遗留表 我正在通过 nhibernate 访问它们 基本的一个实体访问很好 但我确实需要让连接正常工作 理想情况下 我将有主键和外键来定义连接 但由于这些是遗留表 我只有复合 ID 它们是表的索引 索引这些已用于性能原因 因此我无法
  • 解释 gitignore 模式匹配

    我有以下目录树 gt pwd is the repo gt tree a git gitignore README md f1 html f2 html and some more html images river jpg gt 我的中也
  • C5 通用集合库中的小型集合相对来说非常慢 - 有什么办法吗?

    我最近一直在 C 中测试 C5 集合 我很喜欢它们的功能 对于大型集合 性能似乎与通用集合相当 然而 对于小型集合 它们的速度要慢得多 我怀疑相对速度的急剧下降是由于 C5 集合执行的恒定时间操作造成的 我知道的一项操作是触发事件 这可能是
  • 如何在使用 Google 单元测试时在 C 中存根 fgets

    我目前被分配对我在入门训练营期间完成的一些问题进行单元测试 并且我在理解 存根 或 模拟 的概念时遇到问题 我正在使用 Google 单元测试 训练营中的问题已在 C 中解决 int validate input uint32 t inpu
  • ios Coredata 大集插入

    嘿 我连续几天都遇到同样的问题 插入时间逐渐增加 在较低的 ipad 中 它还会因内存问题而崩溃 要插入 20k 记录 需要 4 5 分钟 后台线程会提高效率吗 无论如何我可以优化这个 如果可以的话请帮忙 BOOL addObjectToP
  • jquery 设置 xml cdata

    我在使用 jquery 设置 cdata 节点时遇到问题 使用 text 函数可以轻松获取 cdata 但如果我使用 text jquery gt handy 它不会创建 cdata 节点 这是我的程序 我获取 xml 中的表单数据以加载到
  • 是否可以禁用特定的编译器警告?

    我试图抑制特定的编译器警告 即System Data OracleClient OracleConnection is obsolete 我在这里遇到了这些问题 如何禁用整个解决方案的特定警告 https stackoverflow com
  • 如何手动安装IntelliJ IDEA补丁更新?

    在代理后面更新 IntelliJ 时 我收到以下连接错误 IntelliJ 中的代理 ping 正在工作 连接错误 无法准备更新 无法下载 http download jetbrains com idea IU xxx patch win
  • 使用 Powershell 将图像插入到 VARBINARY(MAX) 类型的 SQL Server 列中

    我被困住了 我正在尝试将图片从硬盘插入到 SQL Server 类型的列中VARBINARY MAX 我把它转换成某种东西 但我什至不确定它是什么 结果看起来像 81 69 20 0 81 69 20 0 81 69 20 0 81 69
  • 使用 Spark 和 Phoenix 将 CSV 文件保存到 hbase 表

    有人可以向我指出使用 Spark 将 csv 文件保存到 Hbase 表的工作示例吗2 2我尝试过但失败的选项 注意 它们都适用于我的 Spark 1 6 凤凰火花 hbase spark it nerdammer bigdata spar
  • TinyMCE JQuery 插件并不总是更新文本区域

    我们的表单有相当多的文本区域 在某些情况下 多达 20 个 每个文本区域都通过 TinyMCE jquery 插件转换为所见即所得编辑器 如下所示 var tinymceoptions script url Scripts tiny mce
  • 如何创建可访问单个数据集的 Google BigQuery 服务帐户?

    有没有办法向给定的客户端 ID 授予对特定 BigQuery 数据集的只读访问权限 我尝试过使用服务帐户 但这提供了对所有数据集的完全访问权限 还尝试从其他应用程序创建服务帐户 并将生成的电子邮件地址与证书一起添加到 BigQuery gt
  • 容器实例 IAM 角色与任务执行角色

    ECS的容器实例IAM角色和任务执行角色有什么区别 我知道任务角色概念 但对容器实例IAM角色和任务执行之间感到困惑 提前致谢 容器实例 IAM 角色 分配给 ECS 任务将部署到的 EC2 实例的角色 如果您要部署到 Fargate 则不
  • 修复了 iframe 中 css 的垂直定位

    我试图让我的底部标题粘贴到 iframe 应用程序内屏幕的底部 并使其始终出现在用户的视图中 即使页面滚动时也是如此 我无法控制外部 iframe 因为它位于不同的域中 标头本身必须位于 iframe 内部 因为我无法控制 iframe 外
  • 在 C 中,为什么 const 变量不能用作数组大小初始值设定项? [复制]

    这个问题在这里已经有答案了 在下面的代码中 const int 不能用作数组大小 const int sz 0 typedef struct char s sz st int main st obj strcpy obj s hello w
  • 通过 Ajax 添加详细信息时出错

    你好frndz 我需要帮助 我正在尝试通过我的表单添加详细信息 但没有获得任何价值 并且错误反映为 添加请求失败 任何人都可以解决我的错误 我不知道该怎么做 这是我的代码webapp js Add company button docume
  • 我正在尝试使用 4 路循环展开来优化此 C 代码

    我想做的是获取此 C 代码并使用称为循环展开的技术对其进行优化 但在本例中我想使用四路循环展开 现在 我理解了这项技术 也理解了这个概念 但我只是不知道如何将其应用到这段代码中 我需要添加一些额外的变量吗 我是否必须在每个循环之后或所有循环
  • java.lang.IllegalArgumentException:如果指定的 JWT 是数字签名的,则必须指定签名密钥

    我正在寻求实施JWT在我的申请中 我正在通过参考以下内容进行一些研发 https stormpath com blog jwt java create verify https stormpath com blog jwt java cre