【问题标题】:Saving oAuth credentials保存 oAuth 凭据
【发布时间】:2018-11-22 09:34:37
【问题描述】:

我正在使用 Google Docs 中的如下代码来管理 Google 日历。

public class CalendarQuickstart {
    private static final String APPLICATION_NAME = "Google Calendar API Java Quickstart";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static final String CREDENTIALS_FOLDER = "credentials"; // Directory to store user credentials.

    /**
     * Global instance of the scopes required by this quickstart.
     * If modifying these scopes, delete your previously saved credentials/ folder.
     */
    private static final List<String> SCOPES = Collections.singletonList(CalendarScopes.CALENDAR_READONLY);
    private static final String CLIENT_SECRET_DIR = "client_secret.json";

    /**
     * Creates an authorized Credential object.
     * @param HTTP_TRANSPORT The network HTTP Transport.
     * @return An authorized Credential object.
     * @throws IOException If there is no client_secret.
     */
    private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
        // Load client secrets.
        InputStream in = CalendarQuickstart.class.getResourceAsStream(CLIENT_SECRET_DIR);
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));

        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
                HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
                .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(CREDENTIALS_FOLDER)))
                .setAccessType("offline")
                .build();
        return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
    }

    public static void main(String... args) throws IOException, GeneralSecurityException {
        // Build a new authorized API client service.
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
        Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
                .setApplicationName(APPLICATION_NAME)
                .build();

        // List the next 10 events from the primary calendar.
        DateTime now = new DateTime(System.currentTimeMillis());
        Events events = service.events().list("primary")
                .setMaxResults(10)
                .setTimeMin(now)
                .setOrderBy("startTime")
                .setSingleEvents(true)
                .execute();
        List<Event> items = events.getItems();
        if (items.isEmpty()) {
            System.out.println("No upcoming events found.");
        } else {
            System.out.println("Upcoming events");
            for (Event event : items) {
                DateTime start = event.getStart().getDateTime();
                if (start == null) {
                    start = event.getStart().getDate();
                }
                System.out.printf("%s (%s)\n", event.getSummary(), start);
            }
        }
    }
}

我把它放到了 Google App Engine 上的 Java 应用程序中。但是,应用程序无法将凭据写入credentials 目录,因为 App Engine 不允许写入磁盘。

解决此问题的一种方法是编写 FileDataStoreFactory 的自定义实现并将凭据存储在 Google 存储桶中。这是推荐的方法吗?这样做安全吗?有更好的选择吗?

【问题讨论】:

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


    【解决方案1】:

    有一个专门介绍使用Google App Engine 的页面,它还提到了如何使用OAuth2DecoratorOAuth2DecoratorFromClientSecrets 连接到其他Google API,例如Google Calendar。

    处理 OAuth 2.0 的最简单方法是使用 App Engine Python 这个库提供的装饰器。这些装饰器处理所有 OAuth 2.0 步骤,您无需使用任何流程、凭据、 或存储对象。

    有两个装饰器类可供选择:

    OAuth2Decorator:使用 OAuth2Decorator 类构建装饰器 使用您的客户 ID 和密码。 OAuth2DecoratorFromClientSecrets:使用 构造装饰器的 OAuth2DecoratorFromClientSecrets 类 使用中描述的 client_secrets.json 文件 OAuth 2.0 页面的 flow_from_clientsecrets() 部分。有 还有两种装饰器类型可供选择:

    oauth_required:任何用 oauth_required 修饰的方法都会完成所有 OAuth 2.0 进入函数前的步骤。体内 函数,可以使用装饰器的http()函数来获取一个Http 已经授权的对象。 oauth_aware:这个装饰器 type 需要比 oauth_required 多一点的代码,但它是 首选,因为它使您可以控制用户体验。为了 例如,您可以显示一个页面来解释为什么用户 重定向到授权服务器。这个装饰器不执行 任何 OAuth 2.0 步骤,但在装饰函数的主体内,您 可以调用这些方便的装饰器函数:has_credentials(): 如果有登录的有效访问凭证,则返回 True 用户。 authorize_url():返回启动 OAuth 2.0 的第一个 URL 步骤。

    【讨论】:

    • 谢谢@noogui。有这方面的 Java 等价物吗?
    【解决方案2】:

    您可以访问此站点并参考how to handle OAuth 2.0 with the App Engine client library for Java。这相当于@noogui 使用 Java 的解决方案。

    这里声明GoogleCredential 实用程序类用于通过 Google 服务进行 OAuth 2.0 授权:

    Google API 支持针对不同类型的客户端应用程序的 OAuth 2.0 流。在所有这些流程中,客户端应用程序请求一个访问令牌,该令牌仅与您的客户端应用程序和被访问的受保护数据的所有者相关联。访问令牌还与定义您的客户端应用程序可以访问的数据类型的有限范围相关联(例如“管理您的任务”)。 OAuth 2.0 的一个重要目标是提供对受保护数据的安全便捷访问,同时最大限度地减少访问令牌被盗时的潜在影响。

    必须遵循authorization code flow,以允许最终用户将受保护数据的访问权限授予其应用程序。这对于网络服务器应用程序或来自 App Engine 的应用程序都有效。

    它还包括一个关于如何配置应用程序以使用Calendar from App Engine 的示例。

    【讨论】:

      猜你喜欢
      • 2016-07-19
      • 2015-01-08
      • 2011-05-09
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 2015-05-23
      • 1970-01-01
      相关资源
      最近更新 更多