OAuth 2.0 访问令牌和刷新令牌

2024-04-12

我很难理解刷新和访问令牌的正确用法。我知道刷新令牌与授权相关,访问令牌与身份验证相关。我想更好地解释我的用例,以便有人可以在这里帮助我。我在 Google Merchant Center 中有一个多帐户中心。我想在我的代码中集成最新的 OAuth 2.0 身份验证机制。我做到了并且可以成功验证。我使用 Google Credential 机制构建凭证对象,并在向 google 发出 httprequest 期间使用 httprequestinitializer 机制进行注入。创建 google credential 对象时,我看到当我执行 googleCredential.getAccessToken() 时没有访问令牌,但是当我执行 googleCredential.refreshToken() 然后执行 googleCredential.getAccessToken() 时,我得到一个 accessToken 。但是,我正在测试如何创建令牌,并且我没有在向谷歌的请求中明确传递这些令牌。我传递的只是带有客户端机密和其他私钥的 googleCredential 对象。我正在做的任务只是通过 cron 脚本将子帐户产品提要上传到谷歌。

我的问题是,

  1. 在此处传递 googleCredential 对象时,我是否必须处理此处的刷新令牌? (假设脚本运行超过一天)
  2. 何时应该使用刷新令牌和访问令牌,在上述用例中对我来说正确的选择是什么? (虽然现在我没有明确传递除 googleCredential 对象之外的任何内容)
  3. 访问令牌和刷新令牌的有效期是多少(与上述用例无关,只是想知道,有些人说刷新令牌为 14 天,有些人说无限期直到用户撤销访问权限,等等)

如果有人澄清我并把我拉出来,我会很高兴。我知道这个平台主要是为了澄清代码问题,但我的谷歌论坛也没有帮助。所以在这里发帖。

抱歉说得太啰嗦了。

提前致谢。


A 刷新令牌需要所谓的离线凭证。这些是可由不在浏览器中运行的应用程序使用的凭据(例如桌面应用程序或一些没有 UI 的批处理),因此无法执行 OAuth2 流程。

请看一下使用 OAuth 2.0 访问 Google API https://developers.google.com/accounts/docs/OAuth2

  1. 如有必要,请刷新访问令牌。

访问令牌的生命周期有限。如果您的应用程序需要在单个访问令牌的生命周期之外访问 Google API,则它可以获得刷新令牌。刷新令牌允许您的应用程序获取新的访问令牌。

注意:将刷新令牌保存在安全的长期存储中,并在它们仍然有效时继续使用它们。限制适用于每个客户端-用户组合以及所有客户端上的每个用户颁发的刷新令牌的数量,并且这些限制是不同的。如果您的应用程序请求足够的刷新令牌来超过其中一项限制,则旧的刷新令牌将停止工作。

更多信息离线访问 https://developers.google.com/accounts/docs/OAuth2WebServer#offline!

在 Java 中,它看起来像这样:

import com.google.api.ads.common.lib.auth.OfflineCredentials;
import com.google.api.ads.common.lib.auth.OfflineCredentials.Api;
import com.google.api.ads.common.lib.auth.OfflineCredentials.ForApiBuilder;
import com.google.api.ads.common.lib.exception.OAuthException;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.client.auth.oauth2.Credential;

// ...

// Generate offline credentials
// With a previously created OAuth2 refresh token (see API examples)
ForApiBuilder forApiBuilder = new OfflineCredentials.Builder().forApi(Api.ADWORDS);
forApiBuilder.withClientSecrets(clientId, clientSecret);
forApiBuilder.withRefreshToken(refreshToken);

Credential credential = null;
try {
  credential = forApiBuilder.build().generateCredential();
} catch (OAuthException e) {
  throw new Exception("The given credential could not be refreshed: " + e.getMessage());
} catch (ValidationException e) {
  throw new Exception("Client ID, client secret or refresh token are not valid: " + e.getMessage());
}

// Build session
// ...

除了客户端 ID 和客户端密钥之外,还需要将刷新令牌传递给凭据生成器。使用有效的 OfflineCredentials,您现在可以为特定的 Google API 构建新会话。

关于你的第三个问题:请参阅以下已接受的答案question https://stackoverflow.com/questions/8953983/do-google-refresh-token-expire

这里是源代码,展示了如何获取刷新令牌Google AdWords(参见范围)通过命令行一次。客户端 ID 和客户端密钥必须作为命令行参数传递。

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;

import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder;
import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder.Api;
import com.google.api.ads.common.lib.auth.GoogleClientSecretsBuilder.GoogleClientSecretsForApiBuilder;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.collect.Lists;

// ...

  private static final String SCOPE = "https://adwords.google.com/api/adwords";

  // This callback URL will allow you to copy the token from the success screen
  private static final String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob";

  public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      System.err.println("Please provide client ID and secret as commandline arguments!");
      System.err.println("If you do not have a client ID or secret, please create one in the API console: https://code.google.com/apis/console#access");
      System.exit(1);
    }

    GoogleClientSecrets clientSecrets = null;
    try {
      Configuration configuration = new PropertiesConfiguration();
      configuration.setProperty("api.adwords.clientId", args[0]);
      configuration.setProperty("api.adwords.clientSecret", args[1]);

      GoogleClientSecretsForApiBuilder googleClientSecretsForApiBuilder = new GoogleClientSecretsBuilder().forApi(Api.ADWORDS);
      googleClientSecretsForApiBuilder.from(configuration);

      clientSecrets = googleClientSecretsForApiBuilder.build();
    } catch (ValidationException e) {
      System.err.println("Invalid client ID or secret!");
      System.exit(1);
    }

    // Get the OAuth2 credential
    Credential credential = getOAuth2Credential(clientSecrets);

    System.out.printf("Your refresh token is: %s\n", credential.getRefreshToken());
    }
  }

  private static Credential getOAuth2Credential(GoogleClientSecrets clientSecrets) throws Exception {
    /*
     * Set the access type to offline so that the token can be refreshed. By
     * default, the library will automatically refresh tokens when it can, but
     * this can be turned off by setting api.adwords.refreshOAuth2Token=false
     */
    GoogleAuthorizationCodeFlow authorizationFlow = new GoogleAuthorizationCodeFlow.Builder(new NetHttpTransport(), new JacksonFactory(), clientSecrets, Lists.newArrayList(SCOPE)).setAccessType("offline").build();

    String authorizeUrl = authorizationFlow.newAuthorizationUrl().setRedirectUri(CALLBACK_URL).build();
    System.out.println("Paste this url in your browser: \n" + authorizeUrl + '\n');

    // Wait for the authorization code
    System.out.println("Type the code you received here: ");
    String authorizationCode = new BufferedReader(new InputStreamReader(System.in)).readLine();

    // Authorize the OAuth2 token
    GoogleAuthorizationCodeTokenRequest tokenRequest = authorizationFlow.newTokenRequest(authorizationCode);
    tokenRequest.setRedirectUri(CALLBACK_URL);
    GoogleTokenResponse tokenResponse = tokenRequest.execute();

    // Create the OAuth2 credential
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport()).setJsonFactory(new JacksonFactory()).setClientSecrets(clientSecrets).build();

    // Set authorized credentials
    credential.setFromTokenResponse(tokenResponse);

    return credential;
  }

该代码最初来自Google AdWords API 示例 https://github.com/googleads/googleads-java-lib/blob/master/examples/adwords_axis/src/main/java/adwords/axis/auth/GetRefreshToken.java。我的版本不是从配置文件中读取,因为我不想将客户端 ID 和机密存储在某些资源文件中(我后来忘记删除它)。这就是为什么这些值作为参数传递给程序的原因。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OAuth 2.0 访问令牌和刷新令牌 的相关文章

随机推荐

  • 当从“using”块中调用“return”时会发生什么? [复制]

    这个问题在这里已经有答案了 如果我有一个带有这样的 using 块的方法 public IEnumerable
  • 是否可以使 java.lang.invoke.MethodHandle 与直接调用一样快?

    我正在比较性能MethodHandle invoke以及直接静态方法调用 这是静态方法 public class IntSum public static int sum int a int b return a b 这是我的基准 Stat
  • Groovy/grails 如何判断一个数据类型?

    确定 groovy 中数据类型的最佳方法是什么 如果是日期等 我想以不同的方式格式化输出 要确定对象的类 只需调用 someObject getClass 您可以将其缩写为someObject class在多数情况下 但是 如果您在Map它
  • qFuzzyCompare 在 Qt 中如何工作

    有什么区别 if a b and if qFuzzyCompare a b 假设变量 a 和 b 是 a 1234 5678 b 1234 5678 注意 我问这个问题是因为我在比较 Qt 中的双打时遇到困难 我想了解如何qFuzzyCom
  • 使用 javascript api 显示来自 facebook 的照片?

    我想使用 javascript api 在我的网页上显示我的 Facebook 相册之一中的照片 我可以使用以下代码读取相册名称 但如何显示其中一张相册的照片 FB api myfacebookid albums function resp
  • 应用程序在 4.0 上崩溃,但在 5.0 上不崩溃

    我试图修复一个奇怪的错误 使用 iOS 4 的用户甚至无法在更新后启动我的应用程序 然后崩溃 iOS 5 设备运行良好 我在上次更新中添加的内容是块 但是 block 应该可以在 ios4 上使用 对吧 iOS 4 3 模拟器运行良好 但
  • EMR 如何处理 s3 存储桶的输入和输出?

    我正在启动一个 EMR 集群 并且已经创建了指定的存储桶在 EMR 文档中 http docs aws amazon com emr latest ManagementGuide emr plan output html 但是我应该如何上传
  • PHP MySQL - 每 6 行插入一个 div?

    PHP
  • jquery ui 自动完成:计数结果

    我想知道是否有一种方法可以计算当您在文本框中键入内容时显示的结果数 计算 li 元素的工作原理 但我敢打赌有一个更聪明的方法 谢谢 我认为直接使用 JQueryUI Events 是不可能的 我一直在寻找方法但没有成功 所有关联的事件仅返回
  • 为什么 不扩展以适应其内容?

    我有一个延伸到屏幕边缘的桌子 但主体仅与屏幕一样宽 导致桌子溢出 Demo http jsfiddle net 6REkj http jsfiddle net 6REkj table tr td test td td test td td
  • 没有 JavaScript 的默认 html 表单焦点

    是否可以在不使用 JavaScript 的情况下在 HTML 表单上设置默认输入焦点 例如
  • 什么时候使用内联函数,什么时候不使用它? [复制]

    这个问题在这里已经有答案了 我知道内联是对编译器的提示或请求 用于避免函数调用开销 那么 根据什么可以确定一个函数是否适合内联呢 在什么情况下应该避免内联 避免函数调用的成本只是故事的一半 do use inline代替 define 很小
  • 如何处理微服务架构中的共享模型

    我的目标是创建一个架构 其中服务应该能够彼此独立部署并且完全自治 但是当您有 2 个服务从数据库读取相同对象类型时该怎么办 就我而言 我有一个套接字服务器 微服务 1 和一个 http 服务器 微服务 2 我的用户使用 http 服务器创建
  • JS Maps v3:带有用户个人资料图片的自定义标记

    两天以来 我一直在努力解决一些我认为很简单的事情 在地图上 我必须为每个用户显示一个标记 其中包含用户 FB 个人资料图片 我想知道如何才能得到与此类似的结果 我所尝试的确实很hackish 我把FB图片作为标记图标 我在标记的标签上放置了
  • intellij idea看不到java 9标准类

    我有一个maven使用的项目Java 9 它导入到IntelliJ IDEA 2017 2 3 Community 但由于某种原因它找不到标准的java类 例如String or Float 例如 当我尝试Setup Project JDK
  • 对象到数组(数组的数组)

    我正在尝试使用函数将对象文字转换为数组数组 使用我拥有的两个示例对象 我正在寻找的最终结果将是 ugh grr foo bar blah 138 from obj1 shambala walawala foofighter Barstool
  • 如何为每个用户构建未读项目警报的数据库

    我只是有一个一般的数据库理论问题 我需要制作类似于显示用户已查看或未查看的帖子 项目 例如在论坛中 或未读电子邮件的内容 我所拥有的是多个用户可以查看的帖子 但需要按实际查看过的用户分开 因此 如果用户 A 浏览了帖子 1 则不会再显示帖子
  • 响应式透明重叠 css 圆圈,文本垂直居中对齐

    似乎无法让我的文本在每个圆圈内对齐中心和垂直 尝试将 h1 文本放入另一个 div 显示表中 但在每个圆形类中包含文本时遇到问题 这是我的代码笔和示例代码 HTML div div class circle1 transparent cla
  • 如何获取给定 PIDL 的 IWMDMStorageControl 接口

    我使用 SHBrowseForFolder 选择 MTP 设备上的文件夹 然后我想从那里复制文件 到那里复制文件 IWMDMStorageControl 接口 来自 Windows Media Format 11 SDK 似乎很合适 但是如
  • OAuth 2.0 访问令牌和刷新令牌

    我很难理解刷新和访问令牌的正确用法 我知道刷新令牌与授权相关 访问令牌与身份验证相关 我想更好地解释我的用例 以便有人可以在这里帮助我 我在 Google Merchant Center 中有一个多帐户中心 我想在我的代码中集成最新的 OA