1

我正在使用GAE中生成的服務帳戶密鑰,在客戶端使用serviceAccounts.keys.create Google IAM API將文件上傳到GCS。此API返回privateKeyData場。我正在使用的客戶端代碼如下:如何在Java的客戶端使用使用serviceAccounts.keys.create API生成的Google雲平臺服務帳戶密鑰?

public class GCSTest { 
    public static final String CLOUD_STORAGE_SCOPE = 
      "https://www.googleapis.com/auth/cloud-platform"; 
    private GoogleCredential credential = null; 
    private HttpTransport HTTP_TRANSPORT = null; 
    private Storage storage = null; 
    private final JsonFactory json_factory = JacksonFactory 
      .getDefaultInstance(); 
    public String APPLICATION_NAME = "GCSTest"; 
    private String privKeyString = 
      <copy the privateKeyData from response of serviceAccounts.keys.create>; 

    public void startTests() { 
     initStorageService(); 
     writeObject(); 
    } 

    private void initStorageService() { 
     List<String> scopeList = new ArrayList<String>(); 
     scopeList.add(CLOUD_STORAGE_SCOPE); 
     HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); 

     byte[] privKeyBytes = Base64.decodeBase64(privKeyString.getBytes()); 
     PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privKeyBytes); 
     KeyFactory kf = KeyFactory.getInstance("RSA"); 
     PrivateKey privateKey = kf.generatePrivate(spec); 
     credential = 
      new GoogleCredential.Builder() 
       .setTransport(HTTP_TRANSPORT) 
       .setJsonFactory(json_factory) 
       .setServiceAccountId(
         "<service_account_name>@<project-id>.iam.gserviceaccount.com") 
       .setServiceAccountScopes(scopeList) 
       .setServiceAccountPrivateKey(privateKey) 
       .setServiceAccountPrivateKeyId(
         "<key_id>") 
       .build(); 

     storage = 
      new Storage.Builder(HTTP_TRANSPORT, json_factory, 
       credential).setApplicationName(APPLICATION_NAME) 
       .build(); 
    } 
    private void writeObject() { 
     String fileName = "StorageSample"; 
     Path tempPath = Files.createTempFile(fileName, ".txt");; 
     Files.write(tempPath, "Sample file".getBytes()); 
     File tempFile = tempPath.toFile(); 
     tempFile.deleteOnExit(); 

     InputStreamContent contentStream = 
       new InputStreamContent("text/plain", new FileInputStream(
         tempFile)); 
     contentStream.setLength(tempFile.length()); 
     StorageObject objectMetadata = new StorageObject().setName(fileName); 
     Storage.Objects.Insert insert = 
      storage.objects().insert(<bucket_name>, 
         objectMetadata, contentStream);; 
     insert.setName(fileName); 
     insert.execute(); 
    } 
} 

不過,我得到java.security.InvalidKeyException: invalid key format exceptionstorage.objects().insert被調用。 這是使用服務帳戶密鑰生成GoogleCredential的正確方法嗎? P.S:我知道JSON或P12密鑰文件。我不想使用它,因爲它不適合我的用例。

回答

0

原來,使用serviceAccounts.keys.create生成的私鑰字符串的密碼是notasecret。以下代碼從API響應中的privateKeyData字段獲取PrivateKey。這PrivateKey可用於獲得GoogleCredential

byte[] privKeyBytes = Base64.decodeBase64(privKeyString.getBytes()); 
KeyStore ks = KeyStore.getInstance("PKCS12"); 
ks.load(new ByteArrayInputStream(privKeyBytes), "notasecret".toCharArray()); 
PrivateKey privateKey = (PrivateKey) ks.getKey("privatekey", "notasecret".toCharArray()); 
0

默認情況下,serviceAccounts.keys.create會生成一個GOOGLE_CREDENTIALS_FILE,它是一個描述密鑰和其他內容的JSON文檔。像gcloud-java客戶端可以讀取這些文件,就像這樣:

StorageOptions options = StorageOptions.builder().projectId(PROJECT_ID) 
    .authCredentials(AuthCredentials.createForJson(
      new FileInputStream(PATH_TO_JSON_KEY))).build(); 
Storage service = options.service(); 

您的代碼,不過,期待一個P12密鑰文件。您可以將JSON文件中的密鑰解壓縮爲這種格式,但更簡單的方法可能是調用serviceAccounts.keys.create並將serviceAccountPrivateKey參數設置爲TYPE_PKCS12_FILE

+0

謝謝。我使用'TYPE_PKCS12_FILE'生成密鑰,但現在我得到了'java.security.InvalidKeyException:IOException:版本不匹配:(支持:00,解析:03'錯誤。 –

相關問題