JWT令牌

JWT令牌

JWT介绍

在JWT之前

在JWT出现之前传统的校验令牌的方法为
校验令牌的方法

出现的问题:
传统授权方法的问题是用户每次请求资源服务,资源服务都需要携带令牌访问认证服务去校验令牌的合法性,并根
据令牌获取用户的相关信息,性能低下。
解决方法:
使用 JWT 的思路是,用户认证通过会得到一个 JWT 令牌,JWT 令牌中已经包括了用户相关的信息,客户端只需要携带 JWT 访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。JWT 令牌授权过程如下图:
JWT 令牌授权过程

JWT介绍

JWT(JSON Web Token)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT 可以使用 HMAC算法或使用 RSA的公钥/私钥对来签名,防止被篡改。
官网
标准

JWT令牌的优点

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

JWT令牌的缺点

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

令牌结构

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

Header

头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)下边是Header部分的内容

    {
        "alg": "HS256",
        "typ": "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:签名所使用的密钥。

JWT入门

Spring Security 提供对 JWT 的支持,我们使用 Spring Security 提供的 JwtHelper 来创建JWT令牌,校验JWT令牌等操作。

生成私钥和公钥

JWT令牌生成采用非对称加密算法

1、生成密钥证书

下边命令生成密钥证书,采用RSA 算法每个证书包含公钥和私钥

keytool -genkeypair -alias xckey -keyalg RSA -keypass xuecheng -keystore xc.keystore -storepass xuechengkeystore

Keytool 是一个 java 提供的证书管理工具,以下是参数的说明
-alias:密钥的别名
-keyalg:使用的hash算法
-keypass:密钥的访问密码
-keystore:密钥库文件名,xc.keystore保存了生成的证书
-storepass:密钥库的访问密码
查询证书信息:

keytool -list -keystore xc.keystore

证书生成

删除别名

keytool -delete -alias xckey -keystore xc.keystore
2、导出公钥

openssl 是一个加解密工具包,这里使用openssl来导出公钥信息。
安装 openssl
安装完成后,配置 openssl 的 path 环境变量,

在命令行进入 xc.keystore 文件所在目录执行如下命令:

keytool -list -rfc --keystore xc.keystore | openssl x509 -inform pem -pubkey
3、生成jwt令牌
@SpringBootTest
@RunWith(SpringRunner.class)
public class JwtTest {
    //生成一个jwt令牌
    @Test
    public void testCreateJwt(){
        //证书文件
        String key_location = "xc.keystore";
        //密钥库密码
        String keystore_password = "xuechengkeystore";
        //访问证书路径
        ClassPathResource resource = new ClassPathResource(key_location);
        //密钥工厂
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource, keystore_password.toCharArray());
        //密钥的密码,此密码和别名要匹配
        String keypassword = "xuecheng";
        //密钥别名
        String alias = "xckey";
        //密钥对(密钥和公钥)
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias,keypassword.toCharArray());
        //私钥
        RSAPrivateKey aPrivate = (RSAPrivateKey) keyPair.getPrivate();
        //定义payload信息
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("id", "123");
        tokenMap.put("name", "mrt");
        tokenMap.put("roles", "r01,r02");
        tokenMap.put("ext", "1");
        //生成jwt令牌
        Jwt jwt = JwtHelper.encode(JSON.toJSONString(tokenMap), new RsaSigner(aPrivate));
        //取出jwt令牌
        String token = jwt.getEncoded();
        System.out.println(token);
    }
}
4、验证jwt令牌
    //资源服务使用公钥验证jwt的合法性,并对jwt解码
    @Test
    public void testVerify(){
        //jwt令牌
        String token ="";
        //公钥
        String publickey = "";
        //校验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);
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值