如何在Java中验证并解码Google OAuth JWT Token?
验证Google JWT Token的正确方法
首先要明确:你当前使用的885016258715-j50dd8tkkee3ttqaqer14s4vd9fvbtbd.apps.googleusercontent.com是Google OAuth的客户端ID,不是公钥。Google的JWT签名公钥是动态发布的,需要从其官方JWKS(JSON Web Key Set)端点获取,而非手动指定静态字符串。
下面提供两种可行的实现方案:
方案一:使用auth0 JWT库正确验证
步骤说明
- 从Google的JWKS端点获取公钥集合:
https://www.googleapis.com/oauth2/v3/certs - 解析JWT头,提取
kid(密钥ID)字段,找到对应的公钥 - 将找到的公钥转换为
RSAPublicKey - 使用该公钥验证JWT,同时指定正确的发行者(issuer)和受众(audience)
代码实现
import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.JWTVerifier; import org.json.JSONObject; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; public class GoogleJwtVerifier { public static void main(String[] args) throws Exception { String token = "eyJhbGciOiJSUz..."; // 你的Google JWT Token String clientId = "885016258715-j50dd8tkkee3ttqaqer14s4vd9fvbtbd.apps.googleusercontent.com"; // 1. 解码JWT获取kid DecodedJWT decodedHeader = JWT.decode(token); String kid = decodedHeader.getKeyId(); // 2. 从Google获取JWKS URL jwksUrl = new URL("https://www.googleapis.com/oauth2/v3/certs"); BufferedReader reader = new BufferedReader(new InputStreamReader(jwksUrl.openStream())); StringBuilder jwksJson = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { jwksJson.append(line); } reader.close(); JSONObject jwks = new JSONObject(jwksJson.toString()); JSONObject keyJson = jwks.getJSONObject(kid); String publicKeyPem = keyJson.getString("value"); // 3. 将PEM格式公钥转换为RSAPublicKey publicKeyPem = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s", ""); byte[] keyBytes = Base64.getDecoder().decode(publicKeyPem); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(spec); // 4. 配置验证器并验证 Algorithm algorithm = Algorithm.RSA256((java.security.interfaces.RSAPublicKey) publicKey, null); JWTVerifier verifier = JWT.require(algorithm) .withIssuer("https://accounts.google.com") // Google JWT的发行者 .withAudience(clientId) // 受众为你的客户端ID .build(); DecodedJWT verifiedJwt = verifier.verify(token); System.out.println("验证成功,Claims:"); System.out.println(verifiedJwt.getClaims()); } }
方案二:使用Google官方验证库(更推荐)
Google提供了专门的库来处理其JWT Token的验证,自动处理公钥获取、密钥轮换等细节,无需手动解析JWKS。
依赖配置(Maven)
<dependency> <groupId>com.google.auth</groupId> <artifactId>google-auth-library-oauth2-http</artifactId> <version>1.20.0</version> <!-- 使用最新稳定版 --> </dependency>
代码实现
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.gson.GsonFactory; import java.util.Collections; public class GoogleOfficialJwtVerifier { public static void main(String[] args) throws Exception { String token = "eyJhbGciOiJSUz..."; // 你的Google JWT Token String clientId = "885016258715-j50dd8tkkee3ttqaqer14s4vd9fvbtbd.apps.googleusercontent.com"; GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new GsonFactory()) .setAudience(Collections.singletonList(clientId)) .build(); GoogleIdToken idToken = verifier.verify(token); if (idToken != null) { GoogleIdToken.Payload payload = idToken.getPayload(); System.out.println("验证成功,Claims:"); System.out.println(payload.toPrettyString()); } else { System.out.println("Token验证失败"); } } }
注意事项
- 方案二会自动缓存Google的公钥,避免重复请求,同时处理密钥轮换,比手动实现更可靠。
- 验证时必须指定正确的
audience(即你的客户端ID)和issuer(Google的发行者固定为https://accounts.google.com),否则验证会失败。
内容的提问来源于stack exchange,提问作者MTilsted
相关产品推荐
相关产品推荐

