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'错误。 –

相关问题