使用Google Drive Oauth 2.0管理访问令牌

7
我正在使用Google API Java客户端从Google App Engine中管理对Google Drive API的访问。我获取用户访问令牌和刷新令牌并将两者保存在我们的数据库中。但我认为只有刷新令牌需要持久化。如何管理访问令牌的过期?你认为这个策略怎么样:
  • 一旦我已经登录到我的Web应用程序,我从存储在数据库中的刷新令牌获取访问令牌,并将其存储在会话中。我该如何从刷新令牌创建Google凭据对象?

  • 当我访问Drive操作时,如果出现过期情况,我会捕获401异常以重新创建访问令牌。

  • 我阅读了Credential and Credential Store,但它似乎已被弃用。现在必须使用StoredCredential。有人有使用这个新接口的示例吗?
    谢谢。

    Diego,你最终解决了吗?因为我由于过期而卡在相同的异常上。 - Aerox
    嗨,我想创建一个凭据对象,给定我的存储在数据存储中的刷新令牌,以便在后台刷新过期的访问令牌,而不需要向用户请求新的授权。我认为你看了这个例子:https://developers.google.com/drive/web/examples/java,因为我正在使用它。 - Aerox
    1
    /** 用我的旧令牌重建了GoogleCredential对象 */ GoogleCredential credentials = new GoogleCredential.Builder() .setClientSecrets(clientId, clientSecret) .setJsonFactory(JSON_FACTORY).setTransport(HTTP_TRANSPORT).build() .setRefreshToken(user.getOAuth2RefreshToken()).setAccessToken(user.getOAuth2AccessToken()); /** 我刷新访问令牌,然后获取它 */ credentials.refreshToken(); newAccess = credentials.getAccessToken(); - Diego Jovanovič
    抱歉,我无法缩进我的注释 :s - Diego Jovanovič
    非常感谢;-) 我会尝试的 :-) - Aerox
    显示剩余2条评论
    1个回答

    10

    如果您正在使用Drive API库,只要您提供了一个具有访问和刷新令牌的凭据,它就会为您处理401异常。

    以下是如何使用StoredCredential构建Credential对象的方法。您可以使用与MemoryDataStoreFactory不同的实现:

    public class ApiCredentialManager {
        private DataStore<StoredCredential> dataStore;
        
            //Put your scopes here
            public static String[] SCOPES_ARRAY = { "https://www.googleapis.com/auth/admin.directory.user" };
        
            private ApiCredentialManager() {
        
                try {
                    dataStore = MemoryDataStoreFactory.getDefaultInstance().getDataStore("credentialDatastore");
                } catch (IOException e) {
                    throw new RuntimeException("Unable to create in memory credential datastore", e);
                }
            }
        
            public static ApiCredentialManager getInstance() {
                if (instance == null)
                    instance = new ApiCredentialManager();
        
                return instance;
            }
        
            public Credential getCredential(String username) throws Exception {
                try {
                    GoogleCredential credential = new GoogleCredential.Builder()
                            .setTransport(new NetHttpTransport())
                            .setJsonFactory(new JacksonFactory())
                            .addRefreshListener(
                                    new DataStoreCredentialRefreshListener(
                                            username, dataStore))
                            .build();
                    
                    if(dataStore.containsKey(username)){
                        StoredCredential storedCredential = dataStore.get(username);
                        credential.setAccessToken(storedCredential.getAccessToken());
                        credential.setRefreshToken(storedCredential.getRefreshToken());
                    }else{
                        //Do something of your own here to obtain the access token.
                        //Most usually redirect the user to the OAuth page
                    }
                    
                    return credential;
                } catch (GeneralSecurityException e) {
                    throw new Exception("isuue while setting credentials", e);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new Exception("isuue while setting credentials", e);
                }
            }
            
            //Call this when you've obtained the access token and refresh token from Google
            public void saveCredential(String username, Credential credential){
                StoredCredential storedCredential = new StoredCredential();
                storedCredential.setAccessToken(credential.getAccessToken());
                storedCredential.setRefreshToken(credential.getRefreshToken());
                dataStore.set(username, storedCredential);
            }
    }
    

    嗨,David,你的示例是否会自动使用刷新令牌获取新的访问令牌?我在http://stackoverflow.com/questions/24117748/how-to-make-a-request-for-an-access-token-using-the-refresh-token-with-google-oa中提出了问题,但没有得到回复 :-( - Aerox
    @Aerox 是的,因为Java中的驱动API客户端会自动刷新令牌(token)如果需要的话。 - David
    它能在后台执行吗?不需要每次都要求用户允许新的OAuth吗? - Aerox
    1
    是的,假设你一开始就有刷新令牌。 - David

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接