用Java创建JSON Web令牌

时间:2013-11-15 13:38:12

标签: java json google-oauth jwt

我正在尝试创建一个JSON Web令牌,以便使用它来通过Google AnalyticsAPI访问进行刷新令牌调用。我采取了服务帐户的方法。

根据这种方法,我需要:

  1. 创建服务帐户
  2. 使用Google Analytics帐户添加为Google Analytics应用创建的电子邮件地址。
  3. 下载priavte密钥文件(.p12)
  4. 使用此priavate密钥和电子邮件地址构建JWT,随后将用于向google auth服务器发出HTTP POST呼叫以获取刷新令牌。
  5. 我不确定我创建JWT的方法是否正确。 Google代码网站上以JWT_Handler.java格式提供的示例讨论了如何创建带有声明部分的JWT,并且仅在缺少标题和签名部分时请求有效负载。这与谷歌为刷新令牌创建JWT的准则相混淆,其中JWT涉及三个部分:

    1. JWT Header
    2. JWT索赔
    3. 签名
    4. 所有这三个部分都是Base64Url编码的。我尝试了以下代码:

      import java.io.FileInputStream;
      import java.io.FileNotFoundException;
      import java.nio.charset.Charset;
      import java.security.KeyStore;
      import java.security.PrivateKey;
      import java.security.Signature;
      import java.util.Calendar;
      import java.util.Enumeration;
      
      import com.google.api.client.util.Base64;
      import com.google.gson.JsonObject;
      public class TestJWT {
      
      private final static Charset UTF8_CHARSET = Charset.forName("UTF-8");
      private static KeyStore myStore = null;
      private static FileInputStream in_cert = null;
      public static void main(String[] args) {
          PrivateKey privateKey = null;       
          try {
              in_cert = new FileInputStream(
                      "D://Google Analytics//ClientLogin//Analytics//%$%%$%$%-privatekey.p12");
      
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          }       
          try {
              myStore = KeyStore.getInstance("PKCS12");
              myStore.load(in_cert, "notasecret".toCharArray());
              String alias = "";       
              Enumeration objEnumeration = myStore.aliases();
              while (objEnumeration.hasMoreElements() == true) {
                  alias = (String) objEnumeration.nextElement();              
                  privateKey = (PrivateKey) myStore.getKey(alias,
                          "notasecret".toCharArray());
              }
          } catch (Exception e1) {
              e1.printStackTrace();
          }
      
          JsonObject header = new JsonObject();
          header.addProperty("alg", "RS256");
          header.addProperty("typ", "JWT");
      
          Calendar cal = Calendar.getInstance();      
          cal.set(1970, 01, 01);      
          String iat = Long.toString((System.currentTimeMillis() - cal.getTimeInMillis())/1000);
          String exp = Long.toString((System.currentTimeMillis() - cal.getTimeInMillis())/1000 + 60000L);
      
          JsonObject claim = new JsonObject();
          claim.addProperty("iss", "$$%$^%&^!%@#$@developer.gserviceaccount.com");
          claim.addProperty("scope", "https://www.googleapis.com/auth/devstorage.readonly");
          claim.addProperty("aud", "https://accounts.google.com/o/oauth2/token");
          claim.addProperty("access_type", "offline");
          claim.addProperty("exp", exp);
          claim.addProperty("iat", iat);
      
      
          System.out.println("Header : " + header);
          String headerStr = header.toString();
          System.out.println("claim : " + claim);
          String claimStr = claim.toString();
      
      
          try {
      
              byte[] headerArr = headerStr.getBytes(UTF8_CHARSET);
              System.out.println(Base64.encodeBase64String(headerArr));
      
              byte[] claimArr = claimStr.getBytes(UTF8_CHARSET);
              System.out.println(Base64.encodeBase64String(claimArr));
      
              String inputStr = Base64.encodeBase64String(headerArr) + "." + Base64.encodeBase64String(claimArr);
      
              System.out.println("Input String : " + inputStr);
              Signature signature = Signature.getInstance("SHA256withRSA");
              signature.initSign(privateKey);
              signature.update(inputStr.getBytes(UTF8_CHARSET));
              System.out.println("Sign : " + signature.sign());
      
              System.out.println("Base64url encoded sign : " + Base64.encodeBase64String(signature.sign()));
      
              System.out.println("Final JWT : " + Base64.encodeBase64String(headerArr) + "." + Base64.encodeBase64String(claimArr) + "." + Base64.encodeBase64String(signature.sign()));
      
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
      
      }
      

1 个答案:

答案 0 :(得分:1)

Prathamesh,这是和你的其他帖子一样的问题吗? (Making Refresh Token Request In Java With JWT through a stand alone application - Not a Web App

为了澄清,使用P12文件签署JWT将允许您获得访问令牌(而不是刷新令牌)。没关系,因为访问令牌是您进行后续API调用所需的。

我强烈建议使用Google的Java客户端库构建JWT并进行签名,您已在其他帖子中粘贴了一个好的示例:

GoogleCredential credentialGA = new GoogleCredential.Builder().setTransport(httpTransport)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId("$#$@#$#$#$@developer.gserviceaccount.com")
        .setServiceAccountScopes(Collections.singleton(AnalyticsScopes.ANALYTICS_READONLY))
        .setServiceAccountPrivateKeyFromP12File(new File("$#$#$%$%$%$-privatekey.p12"))
        .build();
this.analytics = new Analytics.Builder(httpTransport, JSON_FACTORY, credentialGA).setApplicationName("Demo App").build();

是否有特定原因您不想使用客户端库?它将负责创建JWT,签名,发送,构建服务请求,添加授权标头,过期时刷新访问令牌等等。