diff --git "a/_posts/2024-10-29-jwt\347\232\204\351\252\214\350\257\201.md" "b/_posts/2024-10-29-jwt\347\232\204\351\252\214\350\257\201.md" new file mode 100644 index 0000000..06f4e1f --- /dev/null +++ "b/_posts/2024-10-29-jwt\347\232\204\351\252\214\350\257\201.md" @@ -0,0 +1,61 @@ +--- +layout: default +title: JWT的验证 +date: 2024-10-29 13:18 +0800 +categories: jwt +--- + +一般 JWT 是服务器签发,secret 是由服务器保存和验证的,所以一般客户端不需要验证 JWT 的签名是否是伪造的。同样的,对于服务器来说,只需要简单的签名即可,比如 HS256 算法,并不需要对称或者非对称加密。 + +在微服务架构中,我们一般是由 API gateway 统一验证请求中的 JWT 签名,再将请求转发给后端的 API。一般的情况是,后端的 API 是在内网的,所以 API gateway 直接将请求发送到 API,后端 API 也无需验证请求。但是,如果后端 API 同时也暴露在公网,这个时候就需要验证 JWT,以防止来自非 API gateway 的请求。 + +在这种情况下,就不能够使用简单的 HS256 方法,而需要使用非对称加密方式,比如 RS256。具体实现是 API gateway 用私钥签发 JWT,在转发请求到后端 API 的时候带上 JWT。后端 API 通过公钥验证 JWT 的签名是否有效。这个公钥由 API gateway 提供,有时候还会以 JWK 的方式提供公钥。 + +```ruby +require 'openssl' +require 'jwt' +require 'base64' +require 'json' + +# Generate a new RSA key pair +rsa_private = OpenSSL::PKey::RSA.generate(2048) +rsa_public = rsa_private.public_key + +# Generate a new key ID +kid = OpenSSL::Digest::SHA256.hexdigest(rsa_public.to_der) + +# Create the JWKS +jwks = { + keys: [ + { + kty: 'RSA', + kid: kid, + use: 'sig', + alg: 'RS256', + n: Base64.urlsafe_encode64(rsa_public.n.to_s(2), padding: false), + e: Base64.urlsafe_encode64(rsa_public.e.to_s(2), padding: false) + } + ] +} + +puts rsa_public +puts rsa_private + +puts "JWKS: #{jwks.to_json}" + +# Create a payload +payload = { data: 'my secret data' } + +# Encode the payload into a JWT using the private key +token = JWT.encode(payload, rsa_private, 'RS256', { kid: kid }) + +puts "Encrypted Token: #{token}" + +# Decode the JWT using the public key +decoded_token = JWT.decode(token, nil, true, { algorithm: 'RS256', jwks: jwks}) + +# Extract the payload +decoded_payload = decoded_token[0] + +puts "Decoded Payload: #{decoded_payload}" +```