【问题标题】:Java : Google AppEngine : OAuth : Google Drive API to access user's Google Drive contents created by Web ApplicationJava : Google AppEngine : OAuth : Google Drive API 用于访问由 Web 应用程序创建的用户的 Google Drive 内容
【发布时间】:2020-06-27 07:27:58
【问题描述】:

场景:我正在 Google AppEngine 上开发一个 Web 应用程序,用户必须从他们自己的 Google Drive 访问文件。我已经寻找在线帮助,这就是我想出来的。

我已使用此链接寻求帮助,在使用本地机器进行测试时效果很好 https://github.com/gsuitedevs/java-samples/blob/master/drive/quickstart/src/main/java/DriveQuickstart.java

第 1 步(看似简单):启用 Google Drive API 并设置必要的凭据,即 Web 应用程序的 OAuth 2.0 客户端 ID。 (这是在 Google AppEngine 上启用 IAP 时完成的,所以我没有再这样做。每当有人打开 Web 应用程序时,都会要求他/她通过 iap.googleapis.com 进行身份验证并保存详细信息。这很好用)。此外,我已将 Google Drive Scopes 添加到不需要 Google 验证的 OAuth 同意屏幕(../auth/drive.appdata 和 ../auth/drive.file)。

第 2 步:从 OAuth 客户端 ID 下载 credentials.json 并存储在应用程序包根目录中创建的“resources”文件夹中(在主文件夹中,在 java 和 webapp 文件夹旁边)

第 3 步:我创建了一个包含以下代码的测试类 (GoogleDriveServiceTest.class):

String USER_ID1 = UserServiceFactory.getUserService().getCurrentUser().getUserId();
List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_METADATA_READONLY);
NetHttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
InputStream inputStream = 
       GoogleDriveServiceTest.class.getResourceAsStream("/credentials.json");
if (inputStream == null) 
    throw new FileNotFoundException("Required credentials file not found");
GoogleClientSecrets googleClientSecrets = 
            GoogleClientSecrets.load(jsonFactory, new InputStreamReader(inputStream));
    
AppEngineDataStoreFactory appEngineDataStoreFactory = 
                              AppEngineDataStoreFactory.getDefaultInstance();

//IS SOMETHING MISSING HERE???
    
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow
                    .Builder(httpTransport, jsonFactory, googleClientSecrets, SCOPES)
                    .setDataStoreFactory(appEngineDataStoreFactory)
                    .setAccessType("offline")
                    .build();

现在我正在尝试使用此行创建用于访问 Google Drive 的凭据:

Credential credential = flow.loadCredential(USER_ID1);

返回 null。

在我看来,根据我在上面 github 链接的示例中看到的内容,我缺少将凭据分配给 AppEngineDataStoreFactory。但是,我不确定这是否是问题所在,如果是,我该如何解决。

是否有一种直接的方法可以使用从获取的登录用户 ID 分配凭据 UserServiceFactory.getUserService().getCurrentUser().getUserId() ?或者我应该获得 accetoken 并创建凭证?如果有,怎么做?

(我不想使用 javascript,因为它似乎不适合 web 应用程序)

任何帮助都会很棒!!!!

PS:我还想补充一点,用户只需要通过 web 或 android 访问由同一 web 应用程序添加的文件

更新 #1 回复@Aerials: 这是我尝试获取 TokenResponse 的代码:

VerificationCodeReceiver receiver = new GooglePromptReceiver();
(I know above one is not the right option, but I am not able to find any other)    
AuthorizationCodeRequestUrl authorizationUrl =                          
        flow.newAuthorizationUrl().setRedirectUri(receiver.getRedirectUri());
String code = receiver.waitForCode();
(Above line returns: java.util.NoSuchElementException: No line found)
TokenResponse tokenResponse = 
            flow.newTokenRequest(code).setRedirectUri(redirectUri).execute();

更新 #2 用于获取 TokenResponse 和创建凭据并成功连接到 Google Drive 的其余任务的代码:

GenericUrl genericUrl = new GenericUrl(request.getRequestURL().toString());
genericUrl.setRawPath("/googleDriveTest");
String redirectUri = genericUrl.build();

(redirectUri 应与 GCP API Credentials 下 OAuth ClientID 内的授权重定向 URI 匹配。如果现在添加,则需要重新下载 credentials.json 文件)

String redirectUrl =  authorizationCodeFlow
                            .newAuthorizationUrl()
                            .setRedirectUri(redirectUri)
                            .build();
String authorizationCode = request.getParameter("code");
if (authorizationCode == null || authorizationCode.isEmpty())
              response.sendRedirect(redirectUrl);
TokenResponse tokenResponse = authorizationCodeFlow
                                    .newTokenRequest(authorizationCode)
                                    .setRedirectUri(redirectUri).execute();
authorizationCodeFlow.createAndStoreCredential(tokenResponse, USER_ID1);
Credential credential = authorizationCodeFlow.loadCredential(USER_ID1);
Drive service = new Drive.Builder(httpTransport, jsonFactory, credential)
                         .setApplicationName("myapplicationname")
                         .build();

【问题讨论】:

  • 你确定这行:“InputStream inputStream = GoogleDriveServiceTest.class.getResourceAsStream("/credentials.json");"正在查找您的凭据?根据您的文件结构,我知道它应该是“/resources/credentials.json”不?
  • 我认为该行工作正常... flow.getClientId() 返回的值与 credentials.json 中的值匹配
  • 哦,我明白了,它是由您创建的类获取的。

标签: java google-app-engine oauth google-drive-api


【解决方案1】:

您需要先创建凭据并将其存储在流的凭据存储中:

createAndStoreCredential(TokenResponse response, String userId)

能够使用loadCredential(String userId) 加载它们

loadCredential() 方法将返回在给定用户 ID 的 凭据存储 中找到的凭据,如果没有找到,则返回 null。

【讨论】:

  • 非常感谢!!这似乎是正确的方法。但是,我仍在努力让浏览器打开 Google 身份验证屏幕并接收创建 TokenReponse 的“代码”。我已经用我尝试使用的代码更新了我的问题
  • 我相信您会想使用LocalServerReceiver 来启动本地服务器并等待代码。
  • 我不确定从 GAE 运行时这是否有效,即使可以,我也不能这样做,因为同样会访问用户的本地文件夹,这对于 WebApp 来说看起来不太好
  • 好的,我不得不使用 reponse.sendRedirect 来加载 Google 身份验证页面。现在想通了就这么简单!!!我已经用工作代码更新了我的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多