使用auth0构建JWT

写于2019年年底,2020年春,新年好!

JWT

全称 Json Web Token

用于用户认证

用于前后端分离项目(App/微信小程序 无法产生cookie的项目)

文中所提到的 Token泛指身份验证时使用的令牌,而JWT,是json 格式的 web token,两者稍作区别

JWT的构成

JWT 官网 点击前往 ,下列数据解释官网内容:

由三段字符串组成,两端中间用.分隔

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

  • 第一段字符串:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

HEADER:ALGORITHM & TOKEN TYPE

包含生成token使用的算法与token类型

{
   
  "alg": "HS256", //ALGORITHM ,默认算法 哈希256
  "typ": "JWT"  //TOKEN TYPE ,token类型
}

将该JSON字符串做 base64Url 编码 得到eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9


  • 第二段字符串:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

PAYLOAD:DATA

数据载体,可以有自定义数据

{
   
  "sub": "1234567890", // 自定义数据
  "name": "John Doe", // 自定义数据
  "iat": 1516239022	// token起作用时间 、生产日期
}

将该JSON字符串做 base64Url 编码得到 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

base64Url 可被解码,所以不宜将敏感信息写在token中


  • 第三段字符串:SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

VERIFY SIGNATURE

签名验证

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret

) secret base64 encoded
  1. 将第一段 + 第二段 字符串拼接起来(中间用.
  2. 将拼接完成的字符串进行加密, 算法 + 盐 + 密钥
  3. 对算法 加密后的密文再做base64Url编码

JWT实现认证的大致过程

在这里插入图片描述

假设使用HS256算法

  1. 用户提交用户名+密码发送请求给服务端,服务端接受参数使用JWT 创建token返回 (先登录)

  2. 用户第二次发送请求,带上token (登录后的操作 )

  3. 服务端接受token ,将token 分割开 (切割成三部分)

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    
  4. 对第二段字符串进行 base64Url 解密并获取 PAYLOAD数据

    {
         
      "sub": "1234567890", // 自定义数据
      "name": "John Doe", // 自定义数据
      "iat": 1516239022	// token起作用时间 、生产日期
    }
    
  5. 检测 PAYLOAD中的信息是否过期(比较 iatexp 时间)

    为了保证前面两段数据没有被恶意篡改,来校验第三段字符串:

  6. 因为 HS256 不能被反解密(RS256、MD5 亦是如此),所以将第一、二段字符串拼接, 进行 HS256

    `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9` + eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    
    //toHS256
    
  7. 拿着生成的 HS256 密文与第三段字符串进行比较

    • 一致,则校验通过
    • 不同,则不通过

JWT 在JAVA中的应用

Maven库搜索 JWT, jjwt使用率排行第一(优点的话,我粗糙的看了下实现的代码,简明易懂,易使用,但网上说说封装的时候获取信息的能力有限),我这里使用的是 auth0,加入pom.xml 依赖

对于auth0的缺点,应该就是在验证RSA256 加密后的 token的时候,需要给算法实例传递两个key(公钥 + 私钥),这明显不太符合常规情况(常规情况是只需提供公钥即可)

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

观察GitHub中的教程:

https://github.com/auth0/java-jwt

JWT 规定了7个官方字段,提供使用。

  • iss (issuer):发布者
  • sub (subject):主题
  • iat (Issued At):生成签名的时间
  • exp (expiration time):签名过期时间
  • aud (audience):观众,相当于接受者
  • nbf (Not Before):生效时间
  • jti (JWT ID):编号

Using HS256

HS256,签名/验证的时候用的都是同一个密钥,称为对称算法

创建JWT

首先拿到算法实例,用于创建后的签入 sign(传入算法实例)

Algorithm algorithm = Algorithm.HMAC256("secret"); //secret 密钥,只有服务器知道

观察源码:

public static Algorithm HMAC256(String secret) throws IllegalArgumentException {
   
 return new HMACAlgorithm("HS256", "HmacSHA256", secret);
}

实际使用的时候,将 secret 字符串弄得长点,复杂点

使用JWT.create()创建一个 JWTCreator 实例

String token = JWT.create()

使用sign()签入algorithm 在签入之前:

使用withIssuer()给PAYLOAD添加一跳数据 => token发布者

使用withClaim()给PAYLOAD添加一跳数据 => 自定义声明 (key,value)

使用withIssuedAt() 给PAYLOAD添加一条数据 => 生成时间

使用withExpiresAt()给PAYLOAD添加一条数据 => 保质期

@Test
public void creatToken(){
   
    try{
   
        Algorithm algorithm = Algorithm.HMAC256("secret");
        String token = JWT.create()
            .withIssuer("auth0")    // 发布者
            .withIssuedAt(new Date())   // 生成签名的时间
            .withExpiresAt(DateUtils.addHours(new Date(),2))   // 生成签名的有效期,小时
            .withClaim("name","wuyuwei") // 插入数据
            .sign(algorithm);

        System.out.println(token);
    }catch(JWTCreationException e){
   
        e.printStackTrace();
        //如果Claim不能转换为JSON,或者在签名过程中使用的密钥无效,那么将会抛出JWTCreationException异常。
    }


}

withIssuer()用于对参数 添加声明,观察源码:

public JWTCreator.Builder withIssuer(String issuer) {
    
    this.addClaim("iss", issuer);
    return this;
}

private 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值