JWT是toke的一种形式。主要由header(头部)、payload(载荷)、signature(签名) 这三部分字符串组成,这三部分使用"."进行连接,完整的一条JWT值为 h e a d e r . {header}. header.{payload}.${signature}
header
注明使用何种算法制作签名
最开始其实是一个json对象,该JSON包含alg和typ这两个属性,其中alg是签名算法类型,生成JWT中的signature部分时需要使用到,默认为HS256,而typ是当前token类型
{
"alg": "HS256",
"typ": "JWT"
}
paylod
实际讯息的JSON
payload中存放着7个官方定义的属性
iss:签发人
sub:主题
aud:受众
exp:过期时间
nbf:生效时间
iat:签发时间
jti:编号
signature
利用header注明的算法制作出来的乱码
signature会使用header中alg属性定义的签名算法,对header和payload合并的字符串进行加密,加密过后得到的字符串就是signature
提供一个制作JWT的网站
制作JWT
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XPR1Grk7-1615393869470)(https://github.com/stanedward1/MyPicture/blob/master/2103/JWT.png?raw=true)]
下面用ruby来演示相关操作
1.安装gem包并bundle
cd testdemo
gem install jwt
vim Gemfile # add gem 'jwt'
bundle
2.rails c下实践
# 没有设定签名算法类型
2.7.2 :005 > payload = {data: 'test'}
=> {:data=>"test"}
2.7.2 :006 > token = JWT.encode payload, nil, 'none'
=> "eyJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9."
2.7.2 :007 > puts token
eyJhbGciOiJub25lIn0.eyJkYXRhIjoidGVzdCJ9.
=> nil
2.7.2 :008 > decoded_token = JWT.decode token, nil , false
=> [{"data"=>"test"}, {"alg"=>"none"}]
2.7.2 :009 > puts decoded_token
{"data"=>"test"}
{"alg"=>"none"}
=> nil
# 签名算法类型设为HS256(HMAC using SHA-256 hash algorithm)
# HS256 使用同一个「secret_key」进行签名与验证(对称加密)。一旦 secret_key 泄漏,就毫无# 安全性可言了。
# 因此 HS256 只适合集中式认证,签名和验证都必须由可信方进行。
2.7.2 :011 > hmac_secret = "my secret text"
=> "my secret text"
2.7.2 :012 > token = JWT.encode payload, hmac_secret, 'HS256'
=> "eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.X-zKCN2I6HEvCUKysF3wNKzQ8MvpYhilh0GyA264dtQ"
2.7.2 :013 > puts token
eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.X-zKCN2I6HEvCUKysF3wNKzQ8MvpYhilh0GyA264dtQ
=> nil
2.7.2 :014 > decoded_token = JWT.decode token, hmac_secret, true, { algorithm: 'HS256' }
=> [{"data"=>"test"}, {"alg"=>"HS256"}]
2.7.2 :015 > puts decoded_token
{"data"=>"test"}
{"alg"=>"HS256"}
=> nil
2.7.2 :016 > token = JWT.encode payload, nil, 'HS256'
=> "eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.pVzcY2dX8JNM3LzIYeP2B1e1Wcpt1K3TWVvIYSF4x-o"
2.7.2 :017 > puts token
eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.pVzcY2dX8JNM3LzIYeP2B1e1Wcpt1K3TWVvIYSF4x-o
=> nil
2.7.2 :018 > decoded_token = JWT.decode token, nil, true, { algorithm: 'HS256' }
Traceback (most recent call last):
1: from (irb):18
JWT::DecodeError (No verification key available)
2.7.2 :019 > puts decoded_token
{"data"=>"test"}
{"alg"=>"HS256"}
=> nil
# RS256 是使用 RSA 私钥进行签名,使用 RSA 公钥进行验证。公钥即使泄漏也毫无影响,只要确保私钥安全# 就行。
# RS256 可以将验证委托给其他应用,只要将公钥给他们就行。
2.7.2 :021 > rsa_private = OpenSSL::PKey::RSA.generate 2048
=> #<OpenSSL::PKey::RSA:0x00007f848afd3570>
2.7.2 :022 > rsa_public = rsa_private.public_key
=> #<OpenSSL::PKey::RSA:0x00007f848aee8fe8>
2.7.2 :023 > token = JWT.encode payload, rsa_private, 'RS256'
=> "eyJhbGciOiJSUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.J3o8GKKn_0vt_SJl3WINHXgd_u88H...
2.7.2 :024 > puts token
eyJhbGciOiJSUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.J3o8GKKn_0vt_SJl3WINHXgd_u88Hqiar8J5yRTSk_BiiaMduRV1xnkHcBd8A62O08eNQH7gPyPPw2H2RqOUMPg9mVYfTHdyXWKKYipNQ2VVU7lzrXYIwOCHuZhSfzfZHbrMEn7Jc-Tc4Lq0t4FqqUeppIQ-o6yy41DSX_xpGBZ78MqpymkPhtGo871EUU08CXkSPIR8UZHu6YR8WFO-ZlrywgZjeFp6gfGdyb0lev3bV65D2pJsbHOYHToTcHLIum-2EYlu9VVfOuBTn_KncYdPcHVmgPPDTCBL2r487uVW_neUZDoHVGnbhekho57hn7aV-sbC18JP7aQEBiqQOw
=> nil
2.7.2 :025 > decoded_token = JWT.decode token, rsa_public, true, { algorithm: 'RS2
56' }
=> [{"data"=>"test"}, {"alg"=>"RS256"}]
2.7.2 :026 > puts decoded_token
{"data"=>"test"}
{"alg"=>"RS256"}
=> nil
# ES256 和 RS256 一样,都使用私钥签名,公钥验证。算法速度上差距也不大,但是它的签名长度相对短很# 多(省流量),并且算法强度和 RS256 差不多。
2.7.2 :027 > ecdsa_key = OpenSSL::PKey::EC.new 'prime256v1'
=> #<OpenSSL::PKey::EC:0x00007f848a297ac8>
2.7.2 :028 > ecdsa_key.generate_key
=> #<OpenSSL::PKey::EC:0x00007f848a297ac8>
2.7.2 :029 > ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
=> #<OpenSSL::PKey::EC:0x00007f8489f75340>
2.7.2 :030 > ecdsa_public.private_key = nil
=> nil
2.7.2 :031 > token = JWT.encode payload, ecdsa_key, 'ES256'
=> "eyJhbGciOiJFUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.SCYVfzGZ1VtSHuiJhIdEhsEjE_GzU...
2.7.2 :032 > puts token
eyJhbGciOiJFUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.SCYVfzGZ1VtSHuiJhIdEhsEjE_GzUKqDvWMa7By7jc4gtDDvVJss7_s1SCAeBcar2QKNoKy6pN9fSbcYCtFEzw
=> nil
2.7.2 :033 > decoded_token = JWT.decode token, ecdsa_public, true, { algorithm: 'E
S256' }
=> [{"data"=>"test"}, {"alg"=>"ES256"}]
2.7.2 :034 > puts decoded_token
{"data"=>"test"}
{"alg"=>"ES256"}
=> nil
以上三种算法便是JWT中常用的几种算法,并附上我在简书上看到的一个例子!
本篇文章由一文多发平台ArtiPub自动发布