Java中Jwt令牌的快速使用

java中jwt令牌通常是拿来做身份校验,这里介绍jjwt和hutool的jwt共两种的使用方法

一、io.jsonwebtoken下的jwt

1.引入依赖


<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<!----- jdk>8加上下面的,8不用加 -->
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>

2.jwt的分发与解密

这里我们创建一个类,后续可以改成util类

2.1使用固定密钥的加密(对称加密)

固定密钥主要是指在jwt的第三个部分,签名的部分,使用一串固定字符串进行签名并加密,解密的时候用的是同样的密钥。这样简单但是不是很安全,一旦密钥泄露,别人就可以伪造签名。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtil {
    
    public static void main(String[] args) {
        //创建
        //填入信息
        Map<String,Object> map= new HashMap<>();
        map.put("phone",10086);
        //创建
        String token = createJWT("hello", 6000, map);
        System.out.println(token);

        //解析
        Claims claims = parseJWT("hello", token);
        System.out.println(claims);
    }

    /**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘钥
     * @param secretKey jwt秘钥
     * @param ttlMillis jwt过期时间(毫秒)
     * @param claims    设置的信息
     * @return
     */
    public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
        // 指定签名的时候使用的签名算法,header上写的算法
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // jwt过期时间设置
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // jwt的载荷,存了什么信息
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置过期时间
                .setExpiration(exp);

        return builder.compact();
    }

    /**
     * Token解密
     *
     * @param secretKey 秘钥
     * @param token     加密后的token
     * @return
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims;
    }

}

运行后控制台如下:

后续可以把main方法删了,做工具类

2.2使用公私钥加密(非对称加密)

使用密钥对加密其实只是增加了前置操作(获取密钥),并且稍稍修改了签名的地方(加密用私钥,解密用公钥,比较安全)

这里我简单的写一段代码,演示一下

public void test2() {
//-------------------获取密钥对---------------------------------
        String filePath = "your.jks"; // 替换为你的文件路径
        Resource resource = (Resource) new ClassPathResource(filePath);

        KeyStoreKeyFactory keyStoreKeyFactory =
                new KeyStoreKeyFactory(
                        resource,                        //文件路径
                        "yourPassword".toCharArray());    //密码数组

        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(
                "yourAlias",                    //Alias
                "yourPassword".toCharArray());    //密码数组

//-------------------加密---------------------------------
        //过期时间
        Date date = new Date(System.currentTimeMillis() + 600000);
        //注意,加密的时候用的是私钥
        PrivateKey privateKey = keyPair.getPrivate();

        //载荷,这里存一个user=10086
        Map<String,Object> claims =new HashMap<>();
        claims.put("user",10086);

        JwtBuilder builder = Jwts.builder()
                // 设置算法和私钥进行签名
                .setClaims(claims)
                .signWith(SignatureAlgorithm.RS256, privateKey) //加密用私钥!
                .setExpiration(date);
        String token2 = builder.compact();
        System.out.println(token2);

//-------------------解密---------------------------------
        Claims c = Jwts.parser()
                // 设置签名的秘钥  注意,解密用公钥!
                .setSigningKey(keyPair.getPublic())
                // 设置需要解析的jwt
                .parseClaimsJws(token2).getBody();
        System.out.println(c);

    }

结果如下:

二、 cn.hutool下hutool-all的jwt

1.引入依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.11</version>
</dependency>

2.jwt的分发与解密

2.1使用固定密钥的加密

感觉对称加密上,糊涂包并没有jjwt好用,主要是糊涂包的Signer签名器不能直接接受"自定义密钥".getBytes()这种形式的密钥,必须是符合编码格式的,比较麻烦

class JwtExample {

    private static final JWTSigner jwtSigner;

    static {
        //假设密钥是helloWorld   后面改成工具类的时候,取掉main方法,把这块static里面的放到构造函数里就好
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("helloWorld");
        SecretKeySpec keySpec = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
        //设置签名器
        jwtSigner=JWTSignerUtil.createSigner("hs256",keySpec);
    }

//main方法测试一下
    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<>();
        map.put("phone",100860);    //加个手机号为100860
        String token = createJwt(map);
        System.out.println(token);

        JWTPayload jwtPayload = parseJwt(token);
        System.out.println(jwtPayload.toString());

    }

//创建jwt令牌
    public static String createJwt(Map<String,Object> claims){
        Date date = new Date(System.currentTimeMillis() + 600000);

        String token =JWT.create()
                .setPayload("phone",claims.get("phone")) // 注意,糊涂包给一条一条加数据
                .setExpiresAt(date)                      // 一个键值对就一个setPayload()
                .setSigner(jwtSigner) //签名器
                .sign();
        return token;
    }

//解析jwt令牌
    public static JWTPayload parseJwt(String token){
        JWT jwt;
        jwt = JWT.of(token).setSigner(jwtSigner);
        return jwt.getPayload();
    }
}
2.2使用公私钥加密

非对称加密上,只要把密钥对传给签名器就可以了,签名器会自己根据是创建还是解析,来自动使用公钥或者私钥,这就不用我们自己去获取对应的密钥再进行使用,相对于jjwt方便了一些


    public void test(){
//------------------获取密钥对-----------------------------
        String filePath = "yourJks.jks"; // 替换为你的文件路径
        Resource resource = (Resource) new ClassPathResource(filePath);

        KeyStoreKeyFactory keyStoreKeyFactory =
                new KeyStoreKeyFactory(
                        resource,
                        "yourPassword".toCharArray());

        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(
                "yourAlias",
                "yourPassword".toCharArray());
        //设置签名器,请自己在类里定义一个成员变量
        this.jwtSigner = JWTSignerUtil.createSigner("rs256", keyPair);

//--------------------加密--------------------------------------       
        Date date = new Date(System.currentTimeMillis() + 600000);
        String token1 =JWT.create()
                .setPayload("phone", 1008899)    //数据,还是一条一条的插
                .setExpiresAt(date)            //过期日期
                .setSigner(jwtSigner)        //签名器
                .sign();
        System.out.println(token1);

//--------------------解密-------------------------------------------
        JWT jwt;
        jwt = JWT.of(token1).setSigner(jwtSigner); //这里直接把签名器写进去
        System.out.println(jwt.getPayload().toString());

    }

结果如下:

三、注意事项

注意,非对称加密和对称加密的加密算法并不一样,对称加密是hs256而非对称是rs256,当然你可以改成别的,但是要注意跟你的密钥选择要匹配

四、总结

  个人观点哈!如果单论方便来说,在使用对称加密的时候,jjwt更方便一些,并不用对密钥进行各种处理,相反糊涂包的需要对密钥进行编码,并且给符合密钥格式.而在非对称加密的时候,jjwt需要对于加解密取得不同的密钥进行业务处理,而糊涂包的只要把密钥对放进签名器,会自动处理,这样糊涂包就又方便了一些.但是只能说差的不是很多!修改一下也不会很麻烦

  • 17
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java自定义JWT令牌是一种用于身份验证和授权的安全令牌JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式来传输信息,通常用于在网络应用传递用户身份信息。 在Java,可以使用第三方库来实现自定义JWT令牌的生成和验证。以下是一个简单的示例: 1. 导入相关依赖: ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> ``` 2. 创建JWT令牌生成和验证的工具类: ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; public class JwtUtils { private static final String SECRET_KEY = "your-secret-key"; private static final long EXPIRATION_TIME = 86400000; // 24小时 public static String generateToken(String username) { Date now = new Date(); Date expirationDate = new Date(now.getTime() + EXPIRATION_TIME); return Jwts.builder() .setSubject(username) .setIssuedAt(now) .setExpiration(expirationDate) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } public static boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } } ``` 3. 使用JWT令牌生成和验证: ```java public class Main { public static void main(String[] args) { String username = "john.doe"; String token = JwtUtils.generateToken(username); System.out.println("Token: " + token); String extractedUsername = JwtUtils.getUsernameFromToken(token); System.out.println("Extracted username: " + extractedUsername); boolean isValid = JwtUtils.validateToken(token); System.out.println("Is valid token: " + isValid); } } ``` 这是一个简单的示例,你可以根据自己的需求进行更复杂的配置和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值