编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

JWT概念介绍和基本使用(jwt django)

wxchong 2024-07-25 13:51:18 开源技术 15 ℃ 0 评论

jwt

jwt是Json Web Token缩写。它将用户信息加密到token里,服务器不用保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即可验证通过。

  • 优点:在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。
  • 缺点
    (1) 无法作废已颁发的令牌
    (2) 不易应对数据过期的问题

概念介绍

JWT消息构成

一个token分3部分,按顺序为:

  • header:头信息
  • payload:载荷-消息体
  • signature:签名信息
    这里由3部分组成,之间用“.”号做分隔。例如: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

头信息

头部由2部分组织

  • 声明类型,这是是jwt
  • 声明加密的算法,通常直接使用HMAC SHA256

JWT里验证和签名使用的算法,可选择下面的

JWS         算法名称            描述 
HS256     HMAC256          HMAC with SHA-256 
HS384     HMAC384          HMAC with SHA-384 
HS512     HMAC512          HMAC with SHA-512 
RS256     RSA256           RSASSA-PKCS1-v1_5 with SHA-256 
RS384     RSA384           RSASSA-PKCS1-v1_5 with SHA-384 
RS512     RSA512           RSASSA-PKCS1-v1_5 with SHA-512 
ES256     ECDSA256         ECDSA with curve P-256 and SHA-256 
ES384     ECDSA384         ECDSA with curve P-384 and SHA-384
ES512     ECDSA512         ECDSA with curve P-521 and SHA-512

代码指定头信息

 Map<String, Object> map = new HashMap<>();
 map.put("alg", "HS256");
 map.put("typ", "JWT");

载荷(playload)-消息体

载荷就是存放有效信息的地方。基本上有2种数据类型。

  • 标准中注册的声明的数据
  • 自定义数据

在这2部分内部做base64加密。最终将数据保存到JWT的chaims里

  1. 标准中的声明(建议但不强制使用)
 iss:jwt签发者
 sub:jwt所面向的用户
 aud:接受jwt的一方
 exp:jwt的过期时间,这个过期时间必须要大于签发时间
 nbf:定义在什么时间之前,该jwt都是不可用的
 iat:jwt的签发时间
 jti:jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

使用方法

 JWT.create().withHeader(map) //header
             .withClaim("iss", "Service") //payload
             .withClaim("aud", "APP")
             .withIssuedAt(iatDate) //sign time
             .withExpireAt(expiresDate) //expire time
  1. 自定义数据
    这个比较简单,存放我们想放在token中存放的key-value值
    使用方法
    JWT.create().withHeader(map) //header
    .
    withClaim("name", "cy") //payload
    .
    withClaim("user_id", "112233");

签名信息(signature)

jwt的第3部分是一个签证信息,这个签证信息算法如下:

 base64UrlEncode(header) + "." + base64UrlEncode(payload) + 你的256-bit-secret

这部分需要对header和payload进行base64编码,然后通过“.”连接成字符串,然后通过header中申明的加密方式进行加盐secret组合加密,然后就构成了jwt的第3部分。

到目前为止,JWT的api相关知识已经学完了,但是API不够友好,不停地用withClaim放数据。不太好用,下面推荐一个款框架,相当于对JWT的实现框架

JWT

它是为了更友好的在JVM上使用JWT,是基于JWT,JWS,JWK框架的java实现。

参考地址:https://github.com/jwtk/jjwt

基本使用

Maven引入JJWT

 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt-api</artifactId>
     <version>0.10.5</version>
 </dependency>
 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt-impl</artifactId>
     <version>0.10.5</version>
     <scope>runtime</scope>
 </dependency>
 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt-jackson</artifactId>
     <version>0.10.5</version>
     <scope>runtime</scope>
 </dependency>
 <!-- Uncomment this next dependency if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
 <dependency>
     <groupId>org.bouncycastle</groupId>
     <artifactId>bcprov-jdk15on</artifactId>
     <version>1.60</version>
     <scope>runtime</scope>
 </dependency>
 -->

生成token

 import com.sun.javafx.scene.traversal.Algorithm;
 import io.jsonwebtoken.*;
 import io.jsonwebtoken.impl.DefaultJwsHeader;
 
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
 
 private String  SECRET = "DyoonSecret_0581";
 private void getJwtToken(){
       Date iatDate = new Date();
       // expire time
       Calendar nowTime = Calendar.getInstance();
       //有10天有效期
       nowTime.add(Calendar.DATE, 10);
       Date expiresDate = nowTime.getTime();
       Claims claims = Jwts.claims();
       claims.put("name","cy");
       claims.put("userId", "222");
       claims.setAudience("cy");
       claims.setIssuer("cy");
       String token = Jwts.builder().setClaims(claims).setExpiration(expiresDate)
               .signWith(SignatureAlgorithm.HS512, SECRET)
               .compact();
 
   }

上面将token中的载荷放在chaims中,其实chaims是JWT内部维持的一个存放有效信息的地方,不论使用任何API,最终都使用chaims保存信息。 setClaims有2个重载

JwtBuilder setClaims(Claims claims);
JwtBuilder setClaims(Map<String, Object> claims);

解析token

 public void parseJwtToken(String token) {
         try{
 
         }catch (Exception e){
 
         }
         Jws<Claims> jws = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
         String signature = jws.getSignature();
         Map<String, String> header = jws.getHeader();
         Claims Claims = jws.getBody();
 }



Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表