JWT入门

JWT

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT结构

img

token	String	===>	header.payload.singnature

令牌组成

  • 标头(Header)
  • 有效载荷(Payload)
  • 签名(Signature)

JWT通常如下所示: xxxxx.yyyyy.zzzzzheader.payload.singnature

Header

标头通常由两部分组成: 令牌的类型 (即JWT) 和所使用的签名算法, 例如 HMAC SHA256或RSA. 它会使用 Base64 编码组成 JWT 结构的第一部分。

{
    "alg": "HS256",
    "typ": "JWT"
}

Payload

令牌的第二部分是有效负载, 其中包含声明. 声明是有关实体 (通常是用户) 和其他数据的声明. 同样的, 它会使用 Base64 编码组成 JWT 结构的第二部分。

{
    "sub": "1234567890",
    "name": "Jack Ma",
    "admin": true
}

Signature

前面两部分都是使用 Base64 进行编码的,即前端可以解码并获取里面的信息。Signature 需要使用编码后的 header 和 payload 以及我们提供的一个密钥,然后使用 header 中指定的签名算法(HS256)进行签名。签名的作用是保证 JWT 没有被篡改过。

HMACSHA256(
    BASE64UrlEncode(Header) + "." + 
    base64UrlEncode(payload),
    secret);
签名的目的

​ 最后一步签名的过程,实际上是对头部以及负载内容进行签名,防止内容被篡改。如果有人对头部以及负载的内容进行解码之后并修改,再进行编码,最后加上之前的签名组合形成新的 JWT 的话,那么服务器会判断出新的头部和负载形成的签名和 JWT 附带上的签名是不一样的。如果要对新的头部和负载进行签名,在不知到服务器加密使用的密钥的话,得出来的签名也是不一样的。


使用JWT

导入依赖坐标

<!-- jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.11.0</version>
</dependency>

基本使用

获取token
@Test
void jwtCreate() {
    //设置头部,可不设置即默认
    Map<String, Object> header = new HashMap<>();

    //设置时间
    Calendar instance = Calendar.getInstance();
    instance.add(Calendar.MINUTE, 30);

    //使用create方法获取令牌
    String token = JWT.create()
            //header
            .withHeader(header)
            // payload
            .withClaim("userId", 00001)
            .withClaim("username", "root")
            //指定令牌过期时间
            .withExpiresAt(instance.getTime())
            //signature 指定算法并添加密钥(盐)
            .sign(Algorithm.HMAC256("HelloWorld!"));
    
    System.out.println(token);
}

打印结果:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDczMzkxMjEsInVzZXJJZCI6MSwidXNlcm5hbWUiOiJyb290In0.0Qs6CXYvIdKz32OD26VwLnhZLZ1TYwS_W1h49kwDsOQ

验证token
@Test
void verifyToken() {
    //获取验签对象 传入算法并添加之前的密钥
    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("HelloWorld!")).build();
    //验证 通过会返回解码信息
    //算法错误抛出         AlgorithmMismatchException
    //签名不一致抛出       SignatureVerificationException
    //令牌过期抛出         TokenExpiredException
    //失效的payload抛出    InvalidClaimException
    DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDczMzc4NzcsInVzZXJJZCI6MSwidXNlcm5hbWUiOiJyb290In0.6NRNxZujsOP3x7cvhZluj7VHqD0Do8trVrXzGZn8hx8");
    
    System.out.println("userId---" + verify.getClaim("userId").asInt());
    System.out.println("username---"+verify.getClaim("username").asString());
    System.out.println("过期时间---"+verify.getExpiresAt());
}

打印结果:

userId---1 username---root 过期时间---Mon Dec 07 18:44:37 CST 2020

验证结果

验证通过会返回解码信息
算法错误抛出 :AlgorithmMismatchException
签名不一致抛出:SignatureVerificationException
令牌过期抛出: TokenExpiredException
失效的payload抛出: InvalidClaimException


封装工具类

public class JwtUtils {

    /**
     * 设置密钥
     */
    private static final String SING = "Hello,World!";
    /**
     * 令牌过期时间 day
     */
    private static final int TIME = 7;

    /**
     * 生产token
     * @param payload 负载信息
     * @return token信息
     */
    public static String getToken(Map<String, String> payload) {
        //过期时间
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, TIME);
        //创建token
        JWTCreator.Builder builder = JWT.create();
        //将Map中的值放入负载中
        payload.forEach(builder::withClaim);
        //指定过期时间 和 算法
        return builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(SING));
    }

    /**
     * 验证token并返回信息
     */
    public static DecodedJWT getTokenInfo(String token) {
       return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值