zoukankan      html  css  js  c++  java
  • 我爱java系列之---【JWT令牌】

    JWT令牌的优点:

    1、jwt基于json,非常方便解析。 
    2、可以在令牌中自定义丰富的内容,易扩展。
    3、通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。
    4、资源服务使用JWT可不依赖认证服务即可完成授权。

    缺点:

        1、JWT令牌较长,占存储空间比较大。  

    令牌结构:

    JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz

    Header

    头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)

    一个例子如下:

    下边是Header部分的内容

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

    将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。

    Payload

    第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比 如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。

    此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。

    最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。

    一个例子:

    {
    "sub": "1234567890",
    "name": "456",
    "admin": true
    }

    Signature

    第三部分是签名,此部分用于防止jwt内容被篡改。

    这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明 签名算法进行签名。

    一个例子:

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

    base64UrlEncode(header):jwt令牌的第一部分。

    base64UrlEncode(payload):jwt令牌的第二部分。

    secret:签名所使用的密钥。

    使用流程:

    1.生成密钥(保证你电脑的Java环境可以正常运行,这里密钥包括公钥和私钥)

    keytool -genkeypair -alias changgou -keyalg RSA -keypass changgou -keystore changgou.jks -storepass changgou 

    查询证书信息:

    keytool -list -keystore changgou.jks

     2.从密钥中导出公钥

    openssl是一个加解密工具包,这里使用openssl来导出公钥信息。

    安装 openssl(一路默认下一步),下载地址:http://slproweb.com/products/Win32OpenSSL.html

    安装资料目录下的Win64OpenSSL-1_1_1b.exe

    配置openssl的path环境变量,

     

    cmd进入changgou.jks文件所在目录执行如下命令:图中白色部分即为公钥

    keytool -list -rfc --keystore changgou.jks | openssl x509 -inform pem -pubkey

     将上边的公钥拷贝到文本public.key文件中,切记一定要手动合并为一行,可以将它放到需要实现授权认证的工程中的resource文件目录下,哪个工程需要放哪里。

    3.基于私钥生成jwt令牌

    代码百度云下载链接:

    链接:https://pan.baidu.com/s/1gZZT0hglb3XPIKIgJrYTPg
    提取码:zrv6
    复制这段内容后打开百度网盘手机App,操作更方便哦

    3.1导入认证服务

    1) 将课件中changgou_user_auth的工程导入到项目中去,如下图:

     2) 启动eureka,再启动认证服务

    3.2 认证服务中创建测试类

    public class CreateJwtTest {
    
        /***
         * 创建令牌测试
         */
        @Test
        public void testCreateToken(){
            //证书文件路径
            String key_location="changgou.jks";
            //秘钥库密码
            String key_password="changgou";
            //秘钥密码
            String keypwd = "changgou";
            //秘钥别名
            String alias = "changgou";
    
            //访问证书路径
            ClassPathResource resource = new ClassPathResource(key_location);
    
            //创建秘钥工厂
            KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource,key_password.toCharArray());
    
            //读取秘钥对(公钥、私钥)
            KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias,keypwd.toCharArray());
    
            //获取私钥
            RSAPrivateKey rsaPrivate = (RSAPrivateKey) keyPair.getPrivate();
    
            //定义Payload
            Map<String, Object> tokenMap = new HashMap<>();
            tokenMap.put("id", "1");
            tokenMap.put("name", "itheima");
            tokenMap.put("roles", "ROLE_VIP,ROLE_USER");
    
            //生成Jwt令牌
            Jwt jwt = JwtHelper.encode(JSON.toJSONString(tokenMap), new RsaSigner(rsaPrivate));
    
            //取出令牌
            String encoded = jwt.getEncoded();
            System.out.println(encoded);
        }
    }

    4 基于公钥解析jwt令牌

    上面创建令牌后,我们可以对JWT令牌进行解析,这里解析需要用到公钥,我们可以将之前生成的公钥public.key拷贝出来用字符串变量token存储,然后通过公钥解密。

    在changgou-user-oauth创建测试类com.changgou.token.ParseJwtTest实现解析校验令牌数据,代码如下:

    public class ParseJwtTest {
    
        /***
         * 校验令牌
         */
        @Test
        public void testParseToken(){
            //令牌
            String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlcyI6IlJPTEVfVklQLFJPTEVfVVNFUiIsIm5hbWUiOiJpdGhlaW1hIiwiaWQiOiIxIn0.IR9Qu9ZqYZ2gU2qgAziyT38UhEeL4Oi69ko-dzC_P9-Vjz40hwZDqxl8wZ-W2WAw1eWGIHV1EYDjg0-eilogJZ5UikyWw1bewXCpvlM-ZRtYQQqHFTlfDiVcFetyTayaskwa-x_BVS4pTWAskiaIKbKR4KcME2E5o1rEek-3YPkqAiZ6WP1UOmpaCJDaaFSdninqG0gzSCuGvLuG40x0Ngpfk7mPOecsIi5cbJElpdYUsCr9oXc53ROyfvYpHjzV7c2D5eIZu3leUPXRvvVAPJFEcSBiisxUSEeiGpmuQhaFZd1g-yJ1WQrixFvehMeLX2XU6W1nlL5ARTpQf_Jjiw";
    
            //公钥
            String publickey = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFsEiaLvij9C1Mz+oyAmt47whAaRkRu/8kePM+X8760UGU0RMwGti6Z9y3LQ0RvK6I0brXmbGB/RsN38PVnhcP8ZfxGUH26kX0RK+tlrxcrG+HkPYOH4XPAL8Q1lu1n9x3tLcIPxq8ZZtuIyKYEmoLKyMsvTviG5flTpDprT25unWgE4md1kthRWXOnfWHATVY7Y/r4obiOL1mS5bEa/iNKotQNnvIAKtjBM4RlIDWMa6dmz+lHtLtqDD2LF1qwoiSIHI75LQZ/CNYaHCfZSxtOydpNKq8eb1/PGiLNolD4La2zf0/1dlcr5mkesV570NxRmU1tFm8Zd3MZlZmyv9QIDAQAB-----END PUBLIC KEY-----";
    
            //校验Jwt
            Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(publickey));
    
            //获取Jwt原始内容
            String claims = jwt.getClaims();
            System.out.println(claims);
            //jwt令牌
            String encoded = jwt.getEncoded();
            System.out.println(encoded);
        }
    }

     

    愿你走出半生,归来仍是少年!
  • 相关阅读:
    Python入门学习笔记07(time)
    Python入门学习笔记01(常用数据类型)
    Python入门学习笔记04(生成器与迭代器)
    Python入门学习笔记05(内置函数)
    Python入门学习笔记 序
    Python入门学习笔记03(装饰器)
    Python入门学习笔记02(文件的打开、读写)
    Python入门学习笔记06(shelve模块)
    main参数
    [转]如何自动将c++程序接口封装供Python调用
  • 原文地址:https://www.cnblogs.com/hujunwei/p/11432115.html
Copyright © 2011-2022 走看看