开发者社区 问答 正文

我在用JJWT库创建JWT时遇到问题

我在用JJWT库创建JWT时遇到了麻烦:https : //github.com/jwtk/jjwt

我遵循了说明,并提出了这个简单的类:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Calendar;
import java.util.Date;

public class Test {
    public static void main(String[] args){

        Date date = new Date();
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, 1);

        Date expirationDate = cal.getTime();

        String jws = Jwts.builder()
                .setSubject("user")
                .setId("1")
                .setIssuer("me")
                .setIssuedAt(new Date())
                .setExpiration(expirationDate)
                .setIssuedAt(date)
                .signWith(key)
                .compact();

        System.out.println("jws: "+ jws);
        decode(jws);
    }


    public static Jws<Claims> decode(String token){
        return Jwts.parser().setSigningKey(Keys.secretKeyFor(SignatureAlgorithm.HS256)).parseClaimsJws(token);
    }
}

当我运行它时,我得到的输出:

jws: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwianRpIjoiMSIsImlzcyI6InZpY3RvciIsImlhdCI6MTU3NjEwMTAyNiwiZXhwIjoxNTc2MTA0NjI2fQ.28JIsQSc273GT_qjyXEGjyh5KTJJ3thYVGQAa4ZQzvo

和例外:

Exception in thread "main" io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:383)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:513)
    at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:573)
    at Test.decode(Test.java:38)
    at Test.main(Test.java:33)

另外,当我在网站上粘贴我的jwt时:https : //jwt.io/ 它为我提供了正确的(我认为)标题:

{
  "alg": "HS256"
}

以及正确的有效负载:

{
  "sub": "user",
  "jti": "1",
  "iss": "victor",
  "iat": 1576100934,
  "exp": 1576104534
}

但是它说签名无效。

我究竟做错了什么?如何正确创建签名?

展开
收起
垚tutu 2019-12-12 09:16:47 2820 分享 版权
阿里云 AI 助理回答

遇到 SignatureException 通常意味着在验证 JWT 签名时,用于解析的密钥与生成签名时使用的密钥不匹配。从你的代码来看,问题可能出在每次调用 Keys.secretKeyFor(SignatureAlgorithm.HS256) 都会生成一个新的密钥。

为了确保签名和验证使用相同的密钥,你需要将密钥的生成移到一个地方,并且在签名和验证时都使用这个固定的密钥。修改你的代码如下:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Calendar;
import java.util.Date;

public class Test {
    public static void main(String[] args) {
        // 只生成一次密钥并复用
        Key key = generateKey();

        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, 1);

        Date expirationDate = cal.getTime();

        String jws = createJWT(key, "user", "1", "victor", date, expirationDate);

        System.out.println("jws: " + jws);
        try {
            decode(jws, key);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Key generateKey() {
        return Keys.secretKeyFor(SignatureAlgorithm.HS256);
    }

    private static String createJWT(Key key, String subject, String id, String issuer, Date issuedAt, Date expiration) {
        return Jwts.builder()
                .setSubject(subject)
                .setId(id)
                .setIssuer(issuer)
                .setIssuedAt(issuedAt)
                .setExpiration(expiration)
                .signWith(key)
                .compact();
    }

    public static Jws<Claims> decode(String token, Key key) {
        return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
    }
}

在这个修改后的版本中,generateKey() 方法只被调用一次,生成的密钥同时用于创建 JWT 和解码 JWT。这样可以确保签名和验证过程使用的是同一个密钥,应该能解决你遇到的签名不匹配的问题。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答地址: