JWT原理讲解

JWT (JSON WEB TOKEN)

jwt 有3部分组成:(head、Payload、signature)
下面我们将分三步生成JWT的值。

1. Head
头部:一般包含两部分  
{
  "typ": "JWT", // 固定为jwt
  "alg": "HS256" // 加密算法
}

第一部分的值:将 Head 进行 Base64 加密就是 第一部分 的值。

2. Payload
荷载:包含公共部分与自定义部分
{
	// 公共部分, 非强制可以省略。
	"iss": "service-1", // jwt签发者
	"sub": "all",  // jwt所面向的用户
	"aud": "service-2",  // 接收jwt的一方
	"exp": "2020-11-11",  // jwt的过期时间,这个过期时间必须要大于签发时间
	"nbf": "2020-10-01",  // 定义在什么时间之前,该jwt都是不可用的.
	"iat": "2020-01-01",  // jwt的签发时间
	"jti": "@!%^&$uyuyi",  // jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

	// 自定义部分, 可以包含任何信息,因为不安全所以不要放敏感信息。
	"name": "zhangsan",
	"username": "admin"
}

第二部分的值:将 Payload 进行 Base64 加密就是 第二部分 的值。

3. Signature

签证信息:

第三部分的值:将 第一部分的值第二部分的值 连接后,用 Head中alg 指定的加密方式加盐 secret 进行加密后就是 第三部分 的值。
其中盐 secret 的值由服务器保存,且不能泄漏。

4. JWT的值

JWT的值:将 第一部分的值第二部分的值第三部分的值 连接就是JWT的值。
JWT的格式:asdfasdf23.asdflkj.weo8rtuqyoei

5. 使用

用户登录成功后,服务器就根据用户的信息生成一个JWT,并返回给用户,接下来用户每次请求时都携带此JWT,
服务器首先验证该JWT是否是有效的JWT,若有效就解析该JWT,得到其中的 Payload 部分,其中可以根据公共部分的内容做是否过期等验证,若都符合就根据自定义部分的用户信息授予用户相关权限。

6. 总结

安全:

  • 由于 Payload 使用Base64算法加密,所以其中不能放置用户的敏感信息。
  • 服务器端保存的Signature中的 secret 一定不能泄露,由于JWT使用第三部分Signature做数组签名,第三方在不知道 secret 的情况下是无法伪造的,但一旦 secret 泄露,第三方就可以随意伪造JWT。
  • 尽量使用https协议,由于http是明文传输,如果中间有人抓包,就可以获取用户的JWT,变相的就拥有了用户的权限。
  • 尽量设置过期时间,由于JWT长期有效(即使用户更改密码JWT也不会失效),所以JWT的失效不受用户控制。
  • 每次生成JWT时,为了安全可以在Payload部分的jti中加入token。

使用:

  • JWT的生成、验证、解析,一般由实现 JWT 的第三方jar包提供。
  • 我们可以解析JWT后根据其中的 Payload 进行一些验证,比如是否过期,以及IP地址等。
7. java使用入门
  1. 引入依赖:
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.18.2</version>
</dependency>
  1. 定义工具类
package com.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.*;

public class JwtUtil {

    private static String secret = "secret";   // 密钥
    private static String issuer = "hjp";  // 发行者

    private static Base64.Encoder encoder = Base64.getEncoder();
    private static Base64.Decoder decoder = Base64.getDecoder();

	// 生成jwt并base64编码
    public static String genJwt(Map<String,Object> map){
        String result = null;
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTCreator.Builder builder = JWT.create();
            builder.withIssuer(issuer);
            builder.withExpiresAt(new Date(System.currentTimeMillis()+(30*60*1000)));

            Set<String> keys = map.keySet();
            for (String key:keys) {
                Object o = map.get(key);
                if (o instanceof Date){
                    builder = builder.withClaim(key,(Date) o);
                }else if (o instanceof String){
                    builder = builder.withClaim(key,(String) o);
                }else if (o instanceof Integer){
                    builder = builder.withClaim(key,(Integer) o);
                }else if (o instanceof Double){
                    builder = builder.withClaim(key,(Double) o);
                }else if (o instanceof Boolean){
                    builder = builder.withClaim(key,(Boolean) o);
                }
            }
            String sign = builder.sign(algorithm);

            result = encoder.encodeToString(sign.getBytes("UTF-8"));
        }catch (Exception e){

        }
        return result;

    }

	// 验证jwt
    public static boolean valid(String token){
        boolean result = false;

        try{
            String jwt = new String(decoder.decode(token), "UTF-8");

            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(issuer)
                    .build();
            DecodedJWT decodedJWT = verifier.verify(jwt);
            result = true;
        }catch (Exception e){

        }
        return result;
    }
	
	// 解析jwt
    public static Map<String,Object> parseJwt(String token){
        Map<String,Object> map = new HashMap<String, Object>();

        try {
            String jwt = new String(decoder.decode(token), "UTF-8");

            Algorithm algorithm = Algorithm.HMAC256(secret);
            DecodedJWT decodedJWT = JWT.decode(jwt);
            Map<String, Claim> claims = decodedJWT.getClaims();
            Set<String> keys = claims.keySet();
            for (String key:keys) {
                Claim claim = claims.get(key);
                Object value;
                try {
                    value = claim.as(String.class);
                }catch (Exception e1){
                    try {
                        value = claim.as(Integer.class);
                    }catch (Exception e2){
                        try {
                            value = claim.as(Double.class);
                        }catch (Exception e3){
                            try {
                                value = claim.as(Boolean.class);
                            }catch (Exception e4){
                                continue;
                            }
                        }
                    }
                }
                map.put(key,value);
            }
        }catch (Exception e){

        }
        return map;
    }
}

  1. 调用工具类
package com.jwt;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Demo {

    public static void main(String[] args) {

        // 生成jwt
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("name", "张三");
        String jwt = JwtUtil.genJwt(map);
        
        // 解析jwt
        String token = "ZXlKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKSVV6STFOaUo5LmV5SnBjM01pT2lKb2FuQWlMQ0p1WVcxbElqb2k1YnlnNUxpSklpd2laWGh3SWpveE5qTTFOREV4TlRZM2ZRLkgzNXNDcHlyRUJHUWJFV1NFcERLWHhaUGVLM0pDdEN6bWpkd20yNVBrbVE=";
        if (JwtUtil.valid(token)){
            Map<String, Object> parseJwt = JwtUtil.parseJwt(token);
            Set<String> strings = parseJwt.keySet();
            for (String str: strings  ) {
                System.out.println(str+" : "+map.get(str));
            }
        }else {
            System.out.println("jwt无效。");
        }
        
    }
}
8.其他

JWT相关网站: JWT.IO

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值