保存oAuth凭据

时间:2018-06-12 22:01:50

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

我使用Google文档中的代码来管理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应用程序中。但是,由于App Engine不允许写入磁盘,因此该应用程序无法将凭据写入credentials目录。

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

3 个答案:

答案 0 :(得分:1)

有一个专门用于Google App Engine的页面,它还提到了如何使用OAuth2DecoratorOAuth2DecoratorFromClientSecrets连接到Google日历等其他Google API。

  

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

     

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

     

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:这个装饰者   类型需要比oauth_required更多的代码,但确实如此   首选,因为它可以让您控制用户体验。对于   例如,您可以显示一个解释用户原因的页面   重定向到授权服务器。此装饰器不执行   任何OAuth 2.0步骤,但在装饰函数体内你   可以调用这些方便的装饰器函数:has_credentials():   如果有登录的有效访问凭据,则返回True   用户。 authorize_url():返回启动OAuth 2.0的第一个URL   步骤。

答案 1 :(得分:1)

您可以访问此网站,参考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以允许最终用户向其应用程序授予对受保护数据的访问权限。这对于Web服务器应用程序或App Engine的应用程序都有效。

它还包含有关如何配置应用程序以使用Calendar from App Engine的示例。

答案 2 :(得分:-1)

from oauth2client.client import OAuth2Credentials

阅读:

with open(fromfile) as f:
    credentials = OAuth2Credentials.new_from_json(f.read())

要保存:

with open("credentials.json", 'w') as f:
        f.write(credentials.to_json())