2013-12-19 268 views
3

我正在爲Bigquery和Google雲端存儲創建授權課程。在過去,我使用了已棄用的CredentialStore。我試圖使用DataStoreFactory,但是我發現它允許我只使用StoredCredential,而我需要一個Credential。我知道可以從Credential轉換爲StoredCredential,但我不知道如何將它們轉換爲相反方向(StoredCredential to Credential)。我使用例如 Storage.Builder創建我的連接(HttpTransport運輸,JsonFactory jsonFactory,HttpRequestInitializer httpRequestInitializer)授權給Google客戶端

任何人都可以點我一個關於如何實現這一目標的方向?謝謝!

回答

1

在大多數情況下,無論您使用Credential,都可以使用StoreCredential。只有一點你可以使用Credential,它在OAuth回調期間檢索訪問令牌。從那裏,Credential可以轉換爲StoreCredential並存儲到DataStore中。在存儲和檢索之後,所有工作都可以使用StoredCredential。

但有些地方被StoredCredential所不能使用。我剛剛遇到想要創建Google Drive API Service包裝的人。

有辦法解決這個問題與GoogleCredential對象,它可以從StoredCredential創建爲每個這樣的回答:Stored Credential from google api to be reused java

HttpTransport httpTransport = new NetHttpTransport(); 
JsonFactory jsonFactory = new JacksonFactory(); 
GoogleCredential googleCredential = new GoogleCredential.Builder() 
    .setTransport(httpTransport) 
    .setJsonFactory(jsonFactory) 
    .setClientSecrets("client_id", "client_secret").build(); 
credential.setAccessToken(storedCredential.getAccessToken(); 
0

我使用的是谷歌,OAuth的客戶1.22.0.jar 。

我有一個Java服務器,其靜態Service Account憑據可以通過Google Cloud進行身份驗證。

這是我使用的顯着代碼。

這裏的關鍵是添加一個CredentialRefreshListener,當您成功通過身份驗證後,Google OAuth客戶端庫將調用併爲您提供一個可以序列化和存儲的StoredCredential對象。通過編寫或實例化接口的實現,您可以將其存儲並檢索到您選擇的位置。您的DataStore實現是使用DataStoreFactory實現構建的。

在構建我的GoogleCredential後,我可以從我的DataStore中讀取最後一個訪問令牌,刷新令牌和到期日期。 如果訪問令牌不會即將過期,那麼Google客戶端API將使用它登錄。 當它即將過期時,或者這是第一次調用此代碼時,Google Client API將調用刷新監聽器,它將存儲第一個訪問令牌,刷新令牌和到期日期。

import com.google.api.client.auth.oauth2.DataStoreCredentialRefreshListener; 
import com.google.api.client.auth.oauth2.StoredCredential; 
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; 
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; 
import com.google.api.client.http.HttpTransport; 
import com.google.api.client.json.JsonFactory; 
import com.google.api.client.json.jackson2.JacksonFactory; 
import com.google.api.client.util.IOUtils; 
import com.google.api.client.util.store.AbstractDataStore; 
import com.google.api.client.util.store.AbstractDataStoreFactory; 
import com.google.api.client.util.store.DataStore; 
import com.google.api.client.util.store.DataStoreFactory; 
import com.google.api.services.storage.Storage; 
import com.google.api.services.storage.StorageScopes; 
import com.google.api.services.storage.model.StorageObject; 

import java.io.IOException; 
import java.io.Serializable; 
import java.util.Base64; 

public class StackOverflow { 

    public static void main(final String... args) throws Exception { 
    final String clientEmail = "[email protected]"; 
    final HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport(); 
    final JsonFactory jsonFactory = new JacksonFactory(); 
    // This implementation generates an that stores and retrieves StoredCredential objects 
    final DataStoreFactory dataStoreFactory = new AbstractDataStoreFactory() { 
     @Override 
     protected <V extends Serializable> DataStore<V> createDataStore(final String id) { 
     return new MyDataStore<>(this, id); 
     } 
    }; 
    // construct a GoogleCredential object to access Google Cloud 
    final GoogleCredential credential = new GoogleCredential.Builder() 
     .setTransport(transport) 
     .setJsonFactory(jsonFactory) 
     .setServiceAccountId(clientEmail) 
     .setServiceAccountScopes(StorageScopes.all()) 
     .setServiceAccountPrivateKey(readEncryptedPemFile()) 
     .setServiceAccountPrivateKeyId("___static_get_this_from_google_console___") 
     .addRefreshListener(new DataStoreCredentialRefreshListener(clientEmail, dataStoreFactory)) 
     .build(); 
    // See I have an access token, refresh token and expiration date stored in my DataStore. 
    // If so, set them on the GoogleCredential 
    final StoredCredential storedCredential = StoredCredential.getDefaultDataStore(dataStoreFactory).get(clientEmail); 
    if (storedCredential != null) { 
     credential.setAccessToken(storedCredential.getAccessToken()); 
     credential.setRefreshToken(storedCredential.getRefreshToken()); 
     credential.setExpirationTimeMilliseconds(storedCredential.getExpirationTimeMilliseconds()); 
    } 
    // Now I can use Google Cloud 
    final Storage storage = new Storage.Builder(credential.getTransport(), credential.getJsonFactory(), credential).setApplicationName("Aimless").build(); 
    storage.objects().insert("soem bucket", new StorageObject()); 
    } 

    private static class MyDataStore<V extends Serializable> extends AbstractDataStore<V> { 

    MyDataStore(DataStoreFactory dataStoreFactory1, String id1) { 
     super(dataStoreFactory1, id1); 
    } 

    @Override 
    public DataStore<V> set(String key, V value) throws IOException { 
     final String encoded = Base64.getEncoder().encodeToString(IOUtils.serialize(value)); 
     db.save(key, encoded); 
     return this; 
    } 

    @Override 
    public V get(String key) throws IOException { 
     final String encoded = db.get(key); 
     if (encoded == null) { 
     return null; 
     } 
     return IOUtils.deserialize(Base64.getDecoder().decode(encoded)); 
    } 

    // etc. 
    }