传统的token,例如用户登录成功生成对应的令牌,Key为令牌 格式(value: userid)

隐藏了数据真实性,同时将该token存放到redis中,返回对应的真是令牌给客户端存放

客户端每次访问后端请求的时候,会传递该token在请求中,服务器端接收到该token之后,从redis中查询如果存在的情况下,则说明在有效期内,如果在redis中不存在的情况下,则说明过期或者token错误

Jwt底层组成部分:

  1. 头部(header): 存放加密方式  alg:””
{
type=”jwt”  默认为jwt :意思是类型为jwt
alg:”HS256”  :意思是加密算法为hs256
}
  1. 装载的数据(PayLoad)  :携带存放的数据 用户名称 ,用户头像之类  敏感数据不建议存放(存在客户端)  标准中注册的声明(建议不强制使用)

PayLoad其中包含claims。claims是关于实体(常用的是用户信息)和其他数据的声明,claims有三种类型: registered, public, and private claims。

iss:   jwt签发者

sub:  jwt所面向的用户

and:  接受jwt的一方

exp:  jwt的过期时间,这个过期时间必须要大于签发时间

nbf:  定义在什么时间之前,该jwt都是不可以用的

iat:   jwt的签发时间

jti:  jwt的唯一身份标识,主要用来作为一次性token.从而回避重复攻击

{
“userId”:”1234”,
  “username”:”username”,
“过期时间”:“  ”
}

注意:在Payload中不能够存放敏感数,手机号码,密码

Token对应存放在redis或者数据库中的数据。

  1. 验证签名(verify signature);   防止篡改payloal中的数据

Jwt与token最大的区别:

Toeken依赖于Redis来查询数据信息,token存放value数据相当来说比较安全,其他人无法连接我们的redis

Jwt不需要依赖于服务器端,将数据信息内容直接存放在客户端(浏览器)

Jwt优缺点:

优点:

1.无需再在服务器存放用户的数据,减轻服务器端的压力

2.轻量级,json风格比较简单

3.跨语言

缺点:

  1. Token 一旦生成,后期无法修改,也就无法更新jwt有效期
  2. 无法销毁一个token


Base64不是加密和解密,主要是编码和解码,基于64个可打印字符表示二进制数据

程序;

坐标:

<!--         jwt坐标-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.58</version>
        </dependency>
手写jwt
public class JwtTest {
    //手写jwt
    public static void main(String[] args) throws Exception {
      String  signKey="signKey";//盐
    /*   头部(header)
        装载的数据(PayLoad)
        验证签名(verify signature)*/
        JSONObject header = new JSONObject();
        header.put("alg","HS256");
        header.put("typ","jwt");
        JSONObject payLoad = new JSONObject();
          payLoad.put("username","ysw");
          payLoad.put("userage","21");
          payLoad.put("userId","2");
          //base64编码String jwtHeader = Base64.getEncoder().encodeToString(header.toJSONString().getBytes());
String jwtPayLoad = Base64.getEncoder().encodeToString(payLoad.toString().getBytes());
String jwtPayLoadMd5 = Md5Util.encodeByMd5(payLoad.toString()+signKey); //验证签名(verify  signature)//这种可以暴力破解,我们可以加盐
        String jwt=jwtHeader+"."+jwtPayLoad+"."+jwtPayLoadMd5;
        String paload = jwt.split("\\.")[1];
        byte[] bytes= Base64.getDecoder().decode(paload.getBytes());
        String jwtPlayloadStr=new String(bytes, "UTF-8");
        System.out.println("jwtPlayloadStr----"+jwtPlayloadStr);
        String s = Md5Util.encodeByMd5(jwtPlayloadStr + signKey);
        String  payLoadMd5= jwt.split("\\.")[2];
        System.out.println(s.equals(payLoadMd5));
        //验证签名:防止接口参数被篡改  用md5单向加密,不可逆
    }
}

整合JWT:

 

public static String buildJwt() {
            //签名算法,选择SHA-256
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
            String  signKey="signKey";//盐

            //获取当前系统时间
            Date now = new Date(System.currentTimeMillis());
         Date exp = new Date(System.currentTimeMillis()+1000*60*60);
        System.out.println("exSp--------"+exp);
            JSONObject payLoad = new JSONObject();
            payLoad.put("username","ysw");
            payLoad.put("userage","21");
            payLoad.put("userId","2");
            //jwt
            JwtBuilder jwt = Jwts.builder()
                    .setClaims(payLoad)//自定义内容
                    .setId(UUID.randomUUID().toString()) //每个jwt的唯一标识
                    .setIssuedAt(now)        //签发时间
                    .setExpiration(exp)       //过期时间
                    .setSubject("username")    //可以放用户名,用户唯一标识
                    .signWith(signatureAlgorithm, signKey);
            String compact = jwt.compact();
        System.out.println(compact);
        return  compact;
        }
     //解jwt
    public static void main(String[] args) {
        String jwt = buildJwt();
        String  signKey="signKey";//盐
        Claims claims = Jwts.parser().setSigningKey(signKey)
                .parseClaimsJws(jwt).getBody();
        System.out.println(claims);
        int Boolean = (int) claims.get("exp");
        long now = System.currentTimeMillis()/1000;
        long nowex =Boolean- now;
         System.out.println("b---"+Boolean);
        System.out.println(nowex);
    }
}