热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JWT的基本使用

1场景JSONWebToken(JWT)是一种开放标准(RFC7519),它定义了一种紧凑和自包含的方式,用于作为JSON对象在各方之

1 场景

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

官网:https://jwt.io/

2 说明

2.1 结构

在其紧凑的形式中,JSON Web令牌由点(.)分隔的三个部分组成,它们是:

  • Header
  • Payload
  • Signature

因此,JWT通常如下所示:

xxxxx.yyyyy.zzzzz

即,如下格式:

Header.Payload.Signature

2.2 组成

2.2.1 Header

Header通常由两部分组成:令牌的类型,即JWT,以及所使用的签名算法,如HMAC SHA256或RSA。

如下:

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

然后,该JSON是Base64Url编码的,以形成JWT的第一部分。

2.2.2 Payload

令牌的第二部分是Payload,它包含声明claims。声明是关于实体(通常是用户)和附加数据的声明。声明claims有三种类型:registered、public、和private

(1)registered

registered类型的claims。
这些是一组预定义claims,它们不是强制性的,而是推荐的,以提供一组有用的、可互操作的claims。其中包括:iss(发行人)exp(到期时间)sub(主题)aud(目标受众)等。

注意,声明名claims只有三个字符长,因为JWT是为了紧凑。
如:iss、exp、sub、aud

(2)public

这些可以由使用JWTs的人随意定义。但是为了避免冲突,应该在 IANA JSON Web Token Registry 令牌注册表中定义它们,或者将它们定义为包含抗冲突名称空间的URI。

在 IANA JSON Web Token Registry 中定义的claimsName信息如下,定义的为默认定义的claimName的含义:

JWT的基本使用
1615019699644.png

即如果定义的Claim Name,为避免冲突,需参照IANA JSON Web Token Registry中定义的ClaimName,如需`定义其他ClaimName,需不要和这里定义的ClaimName冲突。

可以在此部分配置定义的要传递的业务信息,如:用户信息、部门信息、角色信息等。

(3)private

这些自定义claims是为了在同意使用它们的各方之间共享信息而创建的,它们既不是registered,也不是public的claims。

一个有效的Payload的例子如下:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后对claims进行Base64Url编码,以形成JSON Web令牌的第二部分

请注意,对于已签名的令牌,该信息虽然受到保护,不会被篡改,但任何人都可以读懂。不要将机密信息放在JWT的有效负载或头元素中除非它被加密了

2.2.3 Signature

要创建签名Signature部分,必须获取已编码的Header已编码的Payloadhead中指定的密钥head中指定的算法
根据获取的上述信息,生成签名Signature。

例如,使用HMAC SHA256算法时,签名的生成方式如下:

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

即格式如下:

head算法xxx(base64UrlEncode(json格式的header) + "." +base64UrlEncode(json格式的header),head密钥xxx)

签名用于验证消息在整个过程中没有被篡改,而且,在使用私钥签名的令牌的情况下,它还可以验证JWT的发送方是它所声称的那个人

2.2.4 汇总

输出是三个用点分隔的Base64-URL字符串,它们可以很容易地在HTML和HTTP环境中传递,同时与基于xml的标准(如SAML)相比更紧凑。

下面展示了一个JWT,它对前面的头和有效负载进行了编码,并使用secret对其进行了签名。

JWT的基本使用
encoded-jwt3.png

2.3 在线调试

JWT的在线调试验证地址: jwt.io Debugger

如下:

JWT的基本使用
1615020200659.png

3 Java实现

这里使用java-jwt来实现JWT的操作。

3.1 maven依赖

com.auth0java-jwt3.14.0

3.2 工具类封装


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Verification;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * JWT工具类
 */
public class JWTUtil {
    
    /**
     * 生成签名
     * @param claimMap          claimMap
     * @param secret            密钥
     * @param expireMilliSecond 过期时间-毫秒(如果为null,则无过期时间)
     * @return
     */
    public static String sign(Map claimMap, String secret, Long expireMilliSecond) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTCreator.Builder builder = JWT.create();
        if (claimMap != null && claimMap.size() > 0) {
            for (Map.Entry entry : claimMap.entrySet()) {
                String key = entry.getKey();
                if (key == null || key.equals("")) {
                    continue;
                }
                builder.withClaim(key, entry.getValue());
            }
        }
        if (expireMilliSecond != null) {
            builder.withExpiresAt(new Date(System.currentTimeMillis() + expireMilliSecond));
        }
        return builder.sign(algorithm);
    }
    
    /**
     * 验证token
     * @param token  token
     * @param secret 密钥
     * @return
     */
    public static DecodedJWT verify(String token, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            Verification verification = JWT.require(algorithm);
            JWTVerifier verifier = verification.build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 获取JWT中内容
     * @param jwt       jwt
     * @param claimName claim名称
     * @return
     */
    public static String getClaimValueByJwt(DecodedJWT jwt, String claimName) {
        return jwt.getClaim(claimName).asString();
    }
    
    /**
     * 获取token中内容
     * @param token     token
     * @param claimName claim名称
     * @return
     */
    public static String getClaimValueByToken(String token, String claimName) {
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getClaim(claimName).asString();
    }
}

3.3 使用示例

3.3.1 代码
public static void main(String[] args) throws Exception {
    // ====================【参数定义】====================
    // (1)密钥
    String secret = "x123456";

    // (2)自定义claim内容
    Map claimMap = new HashMap();
    claimMap.put("name", "张三");
    claimMap.put("roleId", "1");

    // (3)超时时间-3小时(单位:毫秒)
    Long expireSecOnd= 3 * 60 * 60 * 1000L;

    System.out.println("====================【生成token】====================");
    String token = JWTUtil.sign(claimMap, secret, expireSecond);
    System.out.println("[生成-token]:" + token);

    System.out.println("n====================【验证token,并获取自定义属性】====================");
    DecodedJWT jwt = JWTUtil.verify(token, secret);
    boolean verifyResult = jwt == null ? false : true;
    System.out.println("[token验证结果]:" + verifyResult);
    System.out.println("[通过验证结果,获取自定义属性]:name--" + JWTUtil.getClaimValueByJwt(jwt, "name"));

    System.out.println("n====================【获取自定义属性】====================");
    System.out.println("[直接通过token,获取自定义属性]:name--" + JWTUtil.getClaimValueByToken(token, "name"));
}
3.3.2 输出结果
====================【生成token】====================
[生成-token]:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlSWQiOiIxIiwibmFtZSI6IuW8oOS4iSIsImV4cCI6MTYxNTA0NjU3N30.ogV3U3dDXdo1hfZBpdr0FxvBbfjOedabNCHZZKLA2Yo

====================【验证token,并获取自定义属性】====================
[token验证结果]:true
[通过验证结果,获取自定义属性]:name--张三

====================【获取自定义属性】====================
[直接通过token,获取自定义属性]:name--张三
3.3.3 官网校验

去jwt在线调试网站上校验: jwt.io Debugger

JWT的基本使用
1615036371599.png

推荐阅读
  • 技术分享:如何在没有公钥的情况下实现JWT密钥滥用
      ... [详细]
  • 加密、解密、揭秘
    谈PHP中信息加密技术同样是一道面试答错的问题,面试官问我非对称加密算法中有哪些经典的算法?当时我愣了一下,因为我把非对称加密与单项散列加 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了安全性要求高的真正密码随机数生成器的概念和原理。首先解释了统计学意义上的伪随机数和真随机数的区别,以及伪随机数在密码学安全中的应用。然后讨论了真随机数的定义和产生方法,并指出了实际情况下真随机数的不可预测性和复杂性。最后介绍了随机数生成器的概念和方法。 ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
author-avatar
靠谱的留一手_267
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有