【问题标题】:How to create a Spring Security Key for signing a JWT token?如何创建用于签署 JWT 令牌的 Spring 安全密钥?
【发布时间】:2019-08-01 19:56:27
【问题描述】:

我使用implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.10.6' 作为依赖项。

我想创建一个 JWT 令牌如下:

@Value("${jwt.token.secret}")
private Key secret;

JwtToken.builder().value(Jwts.builder()
                .setClaims(createClaims(account))
                .setSubject(subject.toString())
                .setIssuedAt(Date.from(createdDateTime))
                .setExpiration(Date.from(expirationDateTime))
                .signWith(secret)
                .compact()).expiration(expirationDateTime.toString()).build()

我曾经在application.properties 中提供一个字符串并引用该密钥,如上所示,但不推荐将字符串作为密钥提供。我应该如何创建密钥?

【问题讨论】:

  • 你为什么使用io.jsonwebtoken:jjwt-api 而不是io.jsonwebtoken:jjwt' 版本:'0.9.1'?
  • @AbdelghaniRoussi 因为 JJWT >= 0.10.0 拆分依赖项以确保正确使用插件。

标签: spring-boot spring-security jjwt


【解决方案1】:

您需要将密钥字符串转换为 Java Key 实例。

您的密钥字符串是 Base64 编码的吗?如果是这样,请执行以下操作:

@Value("${jwt.token.secret}")
private String secret;

private Key getSigningKey() {
  byte[] keyBytes = Decoders.BASE64.decode(this.secret);
  return Keys.hmacShaKeyFor(keyBytes);
}

JwtToken.builder().value(Jwts.builder()
                .setClaims(createClaims(account))
                .setSubject(subject.toString())
                .setIssuedAt(Date.from(createdDateTime))
                .setExpiration(Date.from(expirationDateTime))
                .signWith(getSigningKey())
                .compact()).expiration(expirationDateTime.toString()).build()

如果您的密钥不是 base64 编码的(它可能应该是,因为如果您使用原始密码,例如,您的密钥可能不正确或格式不正确),您可以通过以下方式进行:

private Key getSigningKey() {
  byte[] keyBytes = this.secret.getBytes(StandardCharsets.UTF_8);
  return Keys.hmacShaKeyFor(keyBytes);
}

通常不推荐使用第二个示例,因为它可能意味着您的密钥格式不正确。格式良好、安全的随机密钥不是人类可读的,因此要将其存储为字符串,通常首先对密钥字节进行 base64 编码。

来自文档https://github.com/jwtk/jjwt#jws-key-create

如果您想生成足够强大的 SecretKey 以用于 JWT HMAC-SHA 算法,请使用 Keys.secretKeyFor(SignatureAlgorithm) 辅助方法:

SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); //or HS384 or HS512

在底层,JJWT 使用 JCA 提供者的 KeyGenerator 为给定算法创建具有正确最小长度的安全随机密钥。

如果您有现有的 HMAC SHA SecretKey 的编码字节数组,则可以使用 Keys.hmacShaKeyFor 辅助方法。例如:

byte[] keyBytes = getSigningKeyFromApplicationConfiguration();
SecretKey key = Keys.hmacShaKeyFor(keyBytes);

【讨论】:

  • 您好,我想知道为什么在令牌生成结束时您添加了:设置 setExpiration(Date.from(expirationDateTime)) 后的 expire(expirationDateTime.toString()).build()
  • @aurny2420289 这只是 OP 问题内容的复制粘贴。你看到的是他们JwtToken.builder().value(...) API 的链接,这不是 JJWT 的 API。所以我不知道那个类是做什么的。
  • @LesHazlewood,我正在使用 HS512 和 Keys.secretKeyFor(SignatureAlgorithm.HS256);。一旦我生成了密钥,当使用该方法生成的 access_token 请求进入时,我可以在何处以及如何存储密钥以供将来验证。考虑在验证请求期间我应该使用相同的 secret 。我使用 Spring Boot 2.2.5。有什么线索吗?
  • @Rajesh2389 理想情况下,在您的 @Configuration 类之一中,您将 String 转换为 Key 实例,这将是您可以在其他地方引用的 bean。如果你将它作为一个 bean 引用,Spring 只会创建它的一个实例。
【解决方案2】:

请参阅我对类似问题的回答。

https://stackoverflow.com/a/71149603/1808417

//Generating a safe HS256 Secret key
SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
String secretString = Encoders.BASE64.encode(key.getEncoded());
logger.info("Secret key: " + secretString);

【讨论】:

    猜你喜欢
    • 2018-10-11
    • 2019-08-27
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 2021-02-10
    • 2019-02-05
    • 2022-01-09
    相关资源
    最近更新 更多