JWT令牌基本介绍和入门
JWT介绍
- JWT令牌由三部分组成,每部分中间使用点(.)分割,比如aa.bb.cc;
- Header头部包括令牌的类型(即JWT)及使用的哈希算法(如HMACSHA256或RSA)举例如下:
{
"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)
JWT生成
1.生成密钥证书
采用RSA 算法每个证书包含公钥和私钥
keytool -genkeypair -alias jeromekey -keyalg RSA -keypass jerome -keystore jm.keystore -storepass jeromekeystore
1.创建文件夹jwt_gen(本人创建在F盘) 2.在该文件夹下打开cmd命令 执行脚本,如下:
keytool -genkeypair -alias jeromekey -keyalg RSA -keypass jerome -keystore jm.keystore -storepass jeromekeystore
出现如下: 执行后在jwt_gen夹下生成jm.keystore文件。 查看证书信息:
keytool -list -keystore jm.keystore
其他操作不做演示。 3.导出公钥(需要安装openssl,一个加解密工具包。安装后在path下设置环境变量。本人安装在D盘,目录为D:\OpenSSL-Win64,因此环境变量设置为D:\OpenSSL-Win64\bin,如下图,点击“计算机”右键选择“高级系统设置”->"环境变量“->"用户变量”;如果不行,在系统变量也加上) 执行命令:
keytool -list -rfc --keystore jm.keystore | openssl x509 -inform pem -pubkey
至此,生成公钥就已经完成;下面我们就来测试一下(迫不及待。。。)
2.生成jwt令牌
测试内容可以本地写demo实现,本人是通过搭建一个项目来测试,方便后续拓展。 测试代码如下:
@Test
public void testCreateJwt(){
String keystore = "jm.keystore";
String keystore_password = "jeromekeystore";
ClassPathResource classPathResource = new ClassPathResource(keystore);
String alias = "jeromekey";
String key_password = "jerome";
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource,keystore_password.toCharArray());
KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias, key_password.toCharArray());
RSAPrivateKey aPrivate = (RSAPrivateKey) keyPair.getPrivate();
Map<String,String> body = new HashMap<>();
body.put("name","jerome");
String bodyString = JSON.toJSONString(body);
Jwt jwt = JwtHelper.encode(bodyString, new RsaSigner(aPrivate));
String encoded = jwt.getEncoded();
System.out.println(encoded);
}
生成的jwt令牌为:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiamVyb21lIn0.e2gucjbBaeRTAQnS9DOqBXQbhEZxNS0LjyNRDEFJ_M-eTNzsHU5lRaW8lqyaujPOX39LhwM1dmdX_17TYNFnd1pGAYQi4SGY16ZkHABgvbwyHgPiCSNyoiKD4TcUJNdh3N8e7JWVeIHlNbcpX0YDOzgqi0XXU76jG_-QVh3UpaWNQzQDgIvr6xn0HTGlyVHIrb-zOa__HynKKJTLV195Vx2LqVQy2ZK7zl94LbLUh0bd1T7zjt10Sg-8EJS4QfBE7IqNdYI95B44tDuz5Tz1QC93MZT0Vz-IcWNeJ8LPfWCtQsMyV4CgaUZl12VtPYBwA_OLC_X0fRFOqFEPQuYA8g
3.校验jwt令牌
我们在“生成jwt令牌”中自定义令牌内容为“body.put(“name”,“jerome”)”;校验方法如下:
@Test
public void testCheck(){
String publickey = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj2u/2CjbEnKwwTguNlPFEZFNVA+ec4apjG5ThlZmb3WNIJL9GxTJ2SvBCiTNfVlSD+KginPaLO0z7DqDLjgrTgnL5vVVipNj1Mzx4RCpsSeWtF74Ww2UPjJfvEcgOoKwFEKhqhgGd2YAthcKAzdXhD9jVck4fLOL5jXRgAcIkGCsXSNK2/kDiIH0Oecnoqxz/85YJUEQmWc05sNBp0SsJIhrHNMhrG5nO2BxpM8inMVd5Ja5pNW1om7T9cqRwO19KInVRgxpJgDN7S+DaxpedoP+AhjydG6B5QYV922BkJRUFG0N3A7XWneCIm73D3uxTitgOKd3sg4qebRanrcKYQIDAQAB-----END PUBLIC KEY-----";
String jwtString = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiamVyb21lIn0.e2gucjbBaeRTAQnS9DOqBXQbhEZxNS0LjyNRDEFJ_M-eTNzsHU5lRaW8lqyaujPOX39LhwM1dmdX_17TYNFnd1pGAYQi4SGY16ZkHABgvbwyHgPiCSNyoiKD4TcUJNdh3N8e7JWVeIHlNbcpX0YDOzgqi0XXU76jG_-QVh3UpaWNQzQDgIvr6xn0HTGlyVHIrb-zOa__HynKKJTLV195Vx2LqVQy2ZK7zl94LbLUh0bd1T7zjt10Sg-8EJS4QfBE7IqNdYI95B44tDuz5Tz1QC93MZT0Vz-IcWNeJ8LPfWCtQsMyV4CgaUZl12VtPYBwA_OLC_X0fRFOqFEPQuYA8g";
Jwt jwt = JwtHelper.decodeAndVerify(jwtString, new RsaVerifier(publickey));
String claims = jwt.getClaims();
System.out.println(claims);
}
输出的结果claims为:{“name”:“jerome”};比对一致,与预期一致(有没有一点小小的满足感。。。)。
|