您的位置 首页 java

JAVA-JWT详解

1.什么是JWT

JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑和自成一体的方式,用于在各方之间作为 JSON 对象安全地传输信息。这些信息可以被验证和信任,因为它是数字签名的。JWT可以使用秘密(使用 HMAC 算法)或使用 RSA ECDSA 进行公钥/私钥对进行签名。

以下是JSON Web令牌有用的一些场景:

  • 授权 :这是使用JWT的最常见场景。一旦用户登录,每个后续请求都将包括JWT,允许用户访问该令牌允许的路由、服务和资源。 单点登录 是当今广泛使用JWT的功能,因为它开销小,并且可以轻松地跨不同域使用。
  • 信息交换 :JSON Web令牌是在各方之间安全传输信息的好方法。因为JWT可以签名——例如,使用公钥/ 私钥 对——您可以确定发件人就是他们说的那个人。此外,由于签名是使用标头和有效负载计算的,您还可以验证内容是否未被篡改。

2.JWT结构

JWT由3部分组成:标头( header )、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用 . 进行连接形成最终传输的字符串。

 JWTString=Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode( Payload ),secret)  

1.Header

JWT头 是一个描述JWT元数据的JSON对象,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为 字符串 保存。算法和 type 一般情况使用默认值,进行base64编码将JSON转化为字符串

 {
  "alg":"HS256",
  "typ":"JWT"
}  

2.Payload

有效载荷 部分,是JWT的主体内容部分,也是一个 JSON对象 ,包含需要传递的数据。 JWT指定七个默认字段供选择。

 iss:发行人
exp:到期时间
sub:主题
aud:用户
 nbf :在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT  

这些预定义的字段并不要求强制使用。除以上默认字段外,我们还可以自定义字段, 一般会把包含用户信息的数据放到payload中 ,如下例:userid、username

3.Signature

签名哈希部分是对上面两部分数据签名,需要使用base64编码后的header和payload数据,通过指定的算法生成哈希,以确保数据不会被篡改。首先,需要指定一个密钥(secret)。该密码仅保存在服务器中,并且不能向用户公开。然后,使用header中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名

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

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用 . 分隔,就构成整个JWT对象。

3、 JAVA 中使用JWT

JAVA项目中使用JWT,需要去JWT官网()查找JWT为JAVA提供的类库,在library页面选择JAVA,Auth0点击进入git页面,这里可以找到依赖坐标。

1、引入依赖

创建 maven 项目,在 pom 中添加依赖

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

2、token生成

 /**
     * 生成Token
     * @param userId
     * @param username
     * @return
     */
    public  static  String createToken(String userId,String username){
         Map <String,Object> headerMap = new HashMap<>();
        Calendar cr = Calendar. getInstance ();
        cr.add(Calendar.SECOND,100);
        String token = JWT.create().withHeader(headerMap)                  // 标头(默认值可以省略)
                .withClaim("userId",userId)           //有效负荷(可以根据约定配置多个)
                .withClaim("username",username)       //有效负荷
                .withExpiresAt(cr.getTime())                // 设置有效时间(根据业务需求这是有效时间)
                .sign(Algorithm.HMAC256(SIGN));             // 加签(配置私钥,防止字符串被篡改)
        System.out.println("生成的token为:"+token);
        return token;
    }  

3、验签方法、解码获取信息、常见异常

 /**
     * token 验签
     * token 有效负荷读取
     * @param token
     */
    public static  void  verifyToken(String token){
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SIGN)).build();//创建验证对象
        try{
            DecodedJWT decodedJWT = jwtVerifier.verify(token);//验签
            String userId = decodedJWT.getClaim("userId").asString();//读取有效负荷
            String username = decodedJWT.getClaim("username").asString();//读取有效负荷
            Date expiresAt = decodedJWT.getExpiresAt();//获取token有效期
            System.out.println(userId);
            System.out.println(username);
            System.out.println(expiresAt);
        }catch(TokenExpired Exception  tokenExpiredException){
            System.out.println("超过有效期");
        }catch(AlgorithmMismatchException algorithmMismatchException){
            System.out.println("算法异常");
        }catch(SignatureVerificationException signatureVerificationException){
            System.out.println("签名错误");
        }
    }  

4、整合工具类

 public class JWTUtils {
    public  static  String SIGN = "ASDFse@#w";
    /**
     * 生成Token
     * @param map 用户信息(非敏感信息)
     * @return
     */
    public static String createToken(Map<String, String > map){
        JWTCreator.Builder builder = JWT.create();
        //遍历map 存放到payload
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });
        Calendar cr = Calendar.getInstance();
        cr.add(Calendar.SECOND,100);
        builder.withExpiresAt(cr.getTime());                // 设置有效时间(根据业务需求这是有效时间)
        return builder.sign(Algorithm.HMAC256(SIGN));     // 加签(配置私钥,防止字符串被篡改)
    }

    /**
     * token 验签
     * token 有效负荷读取
     * @param token
     */
    public static DecodedJWT verifyToken(String token){
        return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);//创建验证对象
    }
}  

4、整合 spring boot + jwt,Demo

项目中JWT的使用,多是用来进行安全认证保证接口被正确的权限访问,一般放到拦截器中

   

文章来源:智云一二三科技

文章标题:JAVA-JWT详解

文章地址:https://www.zhihuclub.com/186853.shtml

关于作者: 智云科技

热门文章

网站地图