JWT
JSON Web Tokens 遵循 RFC 7519 标准, 是一种身份认证( Authenticate ) 方式, 充当身份token的同时可以携带一些简单的信息.
简单的Ruby实现
require 'base64'
require 'openssl'
require 'json'
def base64url_encode(str)
Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
end
def jwt_encode(header:, payload:, secret_key:)
header_encoded = base64url_encode(JSON.generate(header))
payload_encoded = base64url_encode(JSON.generate(payload))
header_and_payload_encoded = "#{header_encoded}.#{payload_encoded}"
algorithm = header.dig("alg")
digest = OpenSSL::Digest.new(algorithm.sub('HS', 'sha'))
hmac = OpenSSL::HMAC.digest(digest, secret_key, header_and_payload_encoded)
"#{header_and_payload_encoded}.#{base64url_encode(hmac)}"
end
header = { "alg" => "HS256" }
payload = { "data" => "test" }
p jwt_encode(header: header, payload: payload, secret_key: 'XXxxx')
# eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.twOQcHUwfKdAltXCsYY-5xA5bVxUFlwxqjX28rUgN9k
JWT Gem
有现成的Gem处理以上流程:
require 'jwt'
payload = { data: 'test' }
secret_key = 'XXxxx'
token = JWT.encode payload, secret_key, 'HS256'
# "eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.twOQcHUwfKdAltXCsYY-5xA5bVxUFlwxqjX28rUgN9k"
decoded_token = JWT.decode token, secret_key
# [{ "data" => "test" }, { "alg" => "HS256" }]
当然还可以使用非对称加密算法:
require 'jwt'
require 'openssl'
rsa_private = OpenSSL::PKey::RSA.generate 2048
rsa_public = rsa_private.public_key
token = JWT.encode payload, rsa_private, 'RS256'
# eyJhbGciOiJSUzI1NiJ9.eyJkYXRhIjoidGVzdCJ9.GplO4w1spRgvEJQ3-FOtZr-uC8L45Jt7SN0J4woBnEXG_OZBSNcZjAJWpjadVYEe2ev3oUBFDYM1N_-0BTVeFGGYvMewu8E6aMjSZvOpf1cZBew-Vt4poSq7goG2YRI_zNPt3af2lkPqXD796IKC5URrEvcgF5xFQ-6h07XRDpSRx1ECrNsUOt7UM3l1IB4doY11GzwQA5sHDTmUZ0-kBT76ZMf12Srg_N3hZwphxBtudYtN5VGZn420sVrQMdPE_7Ni3EiWT88j7WCr1xrF60l8sZT3yKCVleG7D2BEXacTntB7GktBv4Xo8OKnpwpqTpIlC05dMowMkz3rEAAYbQ
puts token
decoded_token = JWT.decode token, rsa_public, true, { algorithm: 'RS256' }
# Array
# [
# {"data"=>"test"}, # payload
# {"alg"=>"RS256"} # header
# ]
puts decoded_token
注意: 该 Gem JWT.encode
的时候要自己补全 { algorithm: 'RS256' }
的选项, 否则会报算法不匹配.
Reference
https://github.com/jwt/ruby-jwt
http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html