【问题标题】:Authenticate programmatically to Google with OAuth2使用 OAuth2 以编程方式向 Google 进行身份验证
【发布时间】:2012-06-05 19:32:49
【问题描述】:

如何以编程方式向 Google 进行身份验证? 现在 ClientLogin (https://developers.google.com/accounts/docs/AuthForInstalledApps) 已弃用,我们如何使用 OAuth2 对 Google 执行编程身份验证?

使用 ClientLogin 我们可以发布一个帖子到 https://www.google.com/accounts/ClientLogin 使用电子邮件和密码参数并获取身份验证令牌。

使用 OAuth2 我找不到解决方案!

#

我的应用程序是一个 java 后台进程。 我看到以下链接:developers.google.com/accounts/docs/OAuth2InstalledApp#refresh,如何使用刷新的令牌获取新的访问令牌。

问题是当我有一个新的有效访问令牌时,我找不到一个关于如何实例化 Analytics 对象(例如)以执行查询的 java 示例

这是我的代码,它在调用“execute()”时返回 401 Invalid credentials:

public class Test {

static final String client_id = "MY_CLIENT_ID";
static final String client_secret = "MY_SECRET";
static final String appName = "MY_APP";

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();

static String access_token = "xxxx";
static String refreshToken = "yyyyy";

public static void main (String args[]){

    try {

        GoogleCredential credential = 
            new GoogleCredential.Builder()
                .setTransport(HTTP_TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setClientSecrets(client_id, client_secret).build();
        credential.setAccessToken(access_token);
        credential.setRefreshToken(refreshToken);
        //GoogleCredential
        Analytics analytics = Analytics.builder(HTTP_TRANSPORT, JSON_FACTORY)
            .setApplicationName(appName)
            .setHttpRequestInitializer(credential)
            .build();

        Accounts accounts = analytics.management().accounts().list().execute();
    } catch (Exception e) {
        e.printStackTrace();
    } 
}

有什么问题?

【问题讨论】:

  • 我已经记录了一个使用 Javascript 并在此处获取授权令牌的示例 alexroque.com/?p=307 希望它有所帮助,您要做的是确保我们的返回 URI 在您的 API 控制台中正确设置,并且您从响应中正确解析令牌。
  • 能否请您发布您的解决方案以及它是如何解决的。我也面临同样的问题
  • 能否请您发布您的解决方案的代码。
  • 对于那些寻求解决方案的人,我已经发布了一个作为答案stackoverflow.com/a/34561285/752167

标签: java google-oauth google-login


【解决方案1】:

检查已安装应用程序的 OAuth 2 流程:

https://developers.google.com/accounts/docs/OAuth2InstalledApp

它仍然需要用户第一次使用浏览器进行身份验证,但是您可以存储刷新令牌并将其用于后续请求。

对于替代解决方案,请查看设备流程或服务帐户,它们在同一文档集中进行了说明。

【讨论】:

  • 我检查了已安装应用程序的 OAuth 2 流程,但它没有解释如何刷新访问令牌以及如何执行离线访问(我的 bacgrond 进程需要离线访问)。因此,我遵循了用于 Web 服务器应用程序的 OAuth2(此处记录了离线访问),但我仍然遇到问题。 1)我通过浏览器执行第一个请求,并获得用于离线访问的认证代码 2)我执行认证代码的 java 发布并获得访问令牌和刷新令牌
  • 以下是使用刷新令牌获取新访问令牌的方法:developers.google.com/accounts/docs/OAuth2InstalledApp#refresh
  • 查看 Google Drive Java 教程以获取完整示例,该示例展示了如何解决 OAuth 流程中的所有边缘情况:developers.google.com/drive/examples/java
  • Google 云端硬盘教程讲述了 web 应用程序和用户会话。我需要离线访问才能在预定的后台进程中下载数据。
  • $Andrea,如果您找到了解决方案,对其他人了解最终结果会有所帮助。用有效的方法回答问题并接受它!
【解决方案2】:

对于代表自己进行身份验证的应用程序(即,对另一个应用程序,传统上通过使用共享密码登录角色帐户),Google 提供的 ClientLogin 的 OAuth2 替代方案是服务帐户:

https://developers.google.com/accounts/docs/OAuth2ServiceAccount

【讨论】:

    【解决方案3】:

    我发现 Google Java 客户端过于复杂且文档记录不完善。这是带有 Google Oauth2 的简单明了的 Servlet example。对于后台进程,您需要请求 access_type=offline。正如其他人所提到的,您需要用户进行一次性授权。之后,您可以请求刷新令牌,因为谷歌令牌会在一小时后过期。

    【讨论】:

    • 他们的文档肯定令人沮丧和不透明,但 Google 提供的用于 OAuth 的 Java 客户端确实在幕后为您做了很多。话虽如此,我同意它的实现过于复杂,上面提供的示例确实很有帮助,并且很好地提炼了 Java 中的 OAuth 流程。无论如何,请参阅我的回答,显示如何使用 Google 客户端 stackoverflow.com/a/34561285/752167
    • 上面的例子有效吗?我试过了,请求的资源上没有“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'localhost:2828'。响应的 HTTP 状态代码为 405。@Andrew。感谢您的帮助
    【解决方案4】:

    虽然我很欣赏 OP 最初针对的是 OAuth2InstalledApp 方法,但我想指出一个使用 OAuth2WebServer 方法的可行解决方案。它们没有显着差异,这对我有用。我发现 google OAuth 库非常好,因为它可以为您处理大部分 OAuth 舞蹈,并且可以轻松刷新访问令牌。下面的解决方案取决于使用预先获得的刷新令牌。

    正如接受的答案所述,要使 OAuth 身份验证正常工作(即使对于 Java 后台进程),其中请求依赖于对用户数据的访问

    要求用户第一次使用浏览器进行身份验证,但随后您可以存储刷新令牌并将其用于后续请求。

    从 OP 以前的 cmets 我看到以下内容

    所以我遵循了用于 Web 服务器应用程序的 OAuth2(此处记录了离线访问),但我仍然遇到问题。
    1) 我通过浏览器执行第一个请求,并获得用于离线访问的验证码
    2)我执行验证码的java发布并获取访问令牌和刷新令牌

    我使用的方法更像

    1) 我通过浏览器执行第一个请求并获取刷新令牌以进行离线访问
    2)在java中,我向库提供刷新令牌,库将获得访问令牌等

    具体来说,使用google-api-java-client library 代码非常简单,请注意我没有像OP 那样设置访问令牌,因为我在其他地方调用credential.refreshToken();。 (我检查我是否已经有一个有效的访问令牌,如果没有在 API 调用之前调用 refresh)

      private Credential generateCredentialWithUserApprovedToken() throws IOException,
          GeneralSecurityException {
        JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        InputStreamReader inputStreamReader =
            new InputStreamReader(jsonFileResourceForClient.getInputStream());
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(jsonFactory, inputStreamReader);
        return new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
            .setClientSecrets(clientSecrets).build().setRefreshToken(REFRESH_TOKEN);
      }
    

    请注意,这涵盖了我的方法的第 2 步,第 1 步中提到的REFRESH_TOKEN 可以如下所述获得。

    首先有一个 web app 的预先设置,在 Google console for Credentials 上创建一个 OAuth 2.0 客户端 ID,您最终会得到一个下载的 json 文件,该文件将被读入 GoogleClientSecrets 对象。

    确保将 Google Playground 回调 uri 添加到授权重定向 URI 中

    然后,您就可以为 Playground 准备好您的客户端 ID 和客户端密码,您还可以下载 json 并将其提取到您的 Java 代码中。

    REFRESH_TOKEN 是通过向google oauth playground 发送请求获得的,配置如下。请注意,在第 1 步之前并选择您的范围之前,您应该转到设置以检查您是否提供了自己的凭据并在其下方添加您的客户端 ID 和密码

    注意访问类型为离线,对应this

    这里https://www.youtube.com/watch?v=hfWe1gPCnzc也有一个很好的关于获取刷新令牌的解释

    这足以开始,而且是一次性设置!

    关于刷新令牌,您应该了解它们的生命周期,如文档 here 中所述

    在 oauthplayground 你会看到这个

    但是在文档here 的第 4 点上,它这样说

    嗯。

    另请参阅How do I authorise an app (web or installed) without user intervention? (canonical ?)

    【讨论】:

    • 我通过 Java 快速入门获得了刷新令牌,它打开了一个浏览器并提示用户登录。例如,之后您可以在调试器中看到刷新令牌。似乎是一个肮脏的黑客,但好吧......它的工作原理。
    • 你成就了我的一天。从过去的两个周末开始寻找这个。不要忘记在重定向 uri 中添加 developers.google.com/oauthplayground 而不是 developers.google.com/oauthplayground(最后一个斜杠)
    • “jsonFileResourceForClient”是什么数据类型,是什么?
    • 我会回答自己,“jsonFileResourceForClient”是 InputStreamReader 中的 client_secrets.json。这对我有用:new InputStreamReader(OAuth2TestV2.class.getResourceAsStream("/client_secrets.json"),"UTF-8") 而不是 new InputStreamReader(jsonFileResourceForClient.getInputStream());
    猜你喜欢
    • 2019-11-26
    • 2015-03-24
    • 2017-08-04
    • 1970-01-01
    • 2014-04-29
    • 2013-06-24
    • 2019-05-09
    • 1970-01-01
    • 2015-01-08
    相关资源
    最近更新 更多