关于jwt介绍和代码分析

JWT这是一个很长的字符串,中间用点(.)分隔成三个部分。JWT 内部是没有换行的,一行数据。

1、JWT组成

JWT 的三个部分依次如下。

Header(头部)
Payload(负载)
Signature(签名)

1.1 Header

Header: 是一个json对象,存储元数据
{
“alg”: “HS256”,
“typ”: “JWT”
}
alg:是签名的算法名称(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。元数据的json对象使用base64URL编码.

1.2 Payload

Payload :负载,是一个json对象。是存放传递的数据 ,数据分为Public的和Private的。
Public是JWT中规定的一些字段,可以自己选择使用。

◾iss (issuer):签发人
◾exp (expiration time):过期时间
◾sub (subject):该JWT所面向的用户
◾aud (audience):受众,接收该JWT的一方
◾nbf (Not Before):生效时间
◾iat (Issued At):签发时间
◾jti (JWT ID):编号

Private是自己定义的字段
{
“role”: “经理”,
“name”: “张凡”,
“id”: 2345
}
Playload默认是没有加密的, 以上数据都明文传输的,所以不要放敏感数据.此部分数据也是json对象使用base64URL编码,是一个字符串

1.3 Signature

Signature:签名。签名是对Header和Payload两部分的签名,目的是防止数据被篡改
HMACSHA256(
base64UrlEncode(header) + “.” +
base64UrlEncode(payload),
secret)
签名算法:先指定一个 secret秘钥, 把base64URL的header , base64URL的payload 和 secret秘钥 使用 HMAC SHA256 生成签名字符串

2、JWT的使用方式

1)首先用户使用类似像用户名,密码登录服务器,校验用户身份,服务器返回jwt token
2)客户端获取 jwt token , 使用cookie或者localStorage存储jwt token,但这样不能跨域, 常用的方式放在 请求header 的 Authorization中
Authorization: Bearer
也可以放在 get 或者 post请求的参数中
3)客户端访问其他api接口, 传递token给服务器, 服务器认证token后,返回给请求的数据

3、JJWT库

jjwt 旨在成为最容易使用和理解的库,用于在 JVM 和 Android 上创建和验证 JSON Web 令牌 (JWT)
github地址: https://github.com/jwtk/jjwt
Pom.xml:

<dependency>
   <groupId>io.jsonwebtokengroupId>
   <artifactId>jjwt-apiartifactId>
   <version>0.11.2version>
dependency>
<dependency>
   <groupId>io.jsonwebtokengroupId>
   <artifactId>jjwt-implartifactId>
   <version>0.11.2version>
   <scope>runtimescope>
dependency>
<dependency>
   <groupId>io.jsonwebtokengroupId>
   <artifactId>jjwt-jacksonartifactId> 
   <version>0.11.2version>
   <scope>runtimescope>
dependency>

4、JwtTest

4.1 创建token

Map<String, String> map = new HashMap<>();

String key = "acfd465595224d4db1b23577c3378164";// 就一个key
SecretKey secretKey = Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8));

//准备数据   //载荷
Map<String,Object> payLoad = new HashMap<>();
payLoad.put("uid", 1001);
payLoad.put("realname", true); //实名认证

String jwt =  Jwts.builder().signWith(secretKey, SignatureAlgorithm.HS256)
    .setExpiration(DateUtils.addHours(new Date(), 1))
    .setIssuedAt(new Date())
    .setId(UUID.randomUUID().toString())
    .addClaims(payLoad).compact();

4.2 读取JWT

String jwt = "使用上面例子生成的jwt"//解析jwt的key
String key = "acfd465595224d4db1b23577c3378164";
SecretKey secretKey = Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8));

//1.获取Buider对象
JwtParserBuilder jwtParserBuilder = Jwts.parserBuilder();
//2.设置key
jwtParserBuilder.setSigningKey(secretKey);
//3.获取Parser
JwtParser jwtParser = jwtParserBuilder.build();
//4.解析数据
Jws<Claims> claims = jwtParser.parseClaimsJws(jwt);

//获取数据
Claims body = claims.getBody();
Object uid = body.get("uid");
Integer userId = body.get("uid", Integer.class);

System.out.println(",userId="+uid+",Integer userId="+userId);

4.3 合并成JwtTest

package com.bjpowernode;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.Test;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class JwtTest {

    //创建jwt
    //342903934cb944808920b642616b3e76
    @Test
    public void testCreateJwt() {
        String key = "342903934cb944808920b642616b3e76";

        //创建SeceretKey
        SecretKey secretKey = Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8));

        Date curDate = new Date();
        Map<String,Object> data = new HashMap<>();
        data.put("userId",1001);
        data.put("name","李四");
        data.put("role","经理");
        //创建Jwt,使用Jwts类
        String jwt = Jwts.builder().signWith(secretKey, SignatureAlgorithm.HS256)
                .setExpiration(DateUtils.addMinutes(curDate, 10))
                .setIssuedAt(curDate)
                .setId(UUID.randomUUID().toString())
                .addClaims(data).compact();

        //eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDY5NjQzNjMsImlhdCI6MTY0Njk2Mzc2MywianRpIjoiMjdiMGEyYjgtY2E4Yy00ZGM2LWE3OWItNDdkMGZjNTgwYmJlIiwicm9sZSI6Iue7j-eQhiIsIm5hbWUiOiLmnY7lm5siLCJ1c2VySWQiOjEwMDF9.csFmqoYHl_jylijp5dlWHdzRB0Uce5c71ZtgVv77Id0
        System.out.println("jwt=="+jwt);


    }

    @Test
    public void testReadJwt(){
        String jwt="eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDY5NjY3NzYsImlhdCI6MTY0Njk2NjE3NiwianRpIjoiOWJmNWQwNGMtODY4MS00ZWU0LWFiMjItYmExNTg1YzFhZGMwIiwicm9sZSI6Iue7j-eQhiIsIm5hbWUiOiLmnY7lm5siLCJ1c2VySWQiOjEwMDF9._A3p4rsqdbl8Mxu631axXNEjcMP72c8xVv7GXtmLg1o";
        String key = "342903934cb944808920b642616b3e76";
        //创建SeceretKey
        SecretKey secretKey = Keys.hmacShaKeyFor(key.getBytes(StandardCharsets.UTF_8));

        //解析jwt , 没有异常,解析成功
        Jws<Claims> claims = Jwts.parserBuilder().setSigningKey(secretKey).build()
                              .parseClaimsJws(jwt);

        //读数据
        Claims body = claims.getBody();
        Integer userId = body.get("userId", Integer.class);
        System.out.println("userId="+userId);
        Object uid = body.get("userId");
        System.out.println("uid="+uid);

        Object name = body.get("name");
        if( name != null ){
            String str= (String)name;
            System.out.println("str = " + str);
        }

        String jwtId = body.getId();
        System.out.println("jwtId="+jwtId);

        Date expiration = body.getExpiration();
        System.out.println("过期时间:"+expiration);


    }
}

5、异常

读取jwt可能发生的异常
KeyException key异常
SignatureException 签名异常
ExpiredJwtException 过期异常
InvalidClaimException 无效Payload异常
JwtException Jwt父类异常,总异常

你可能感兴趣的:(java,json,前端,java)