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
)仅用于这个简单的测试演示 - 永远不要将密钥硬编码到源代码中,更不用说将它们设为静态常量,因为它们很容易被反编译。