【问题标题】:Offline Access to google calendar using java使用java离线访问谷歌日历
【发布时间】:2013-01-01 20:15:50
【问题描述】:

我们有代码可以将我们的应用程序日历与登录用户的谷歌日历同步。该代码使用 AuthSub 和 CalendarService 类,但它不提供使用访问令牌和刷新令牌对谷歌日历的离线访问,因为我想使用日历类使用 OAuth v3。我在将旧代码合并到没有 getFeed() 函数的新 v3 Calendar 类时遇到问题。这是我的应用程序中的一些代码

if(StringUtil.isValid(request.getQueryString())) {
                onetimeUseToken = AuthSubUtil.getTokenFromReply(request.getQueryString());
            }       

            if(StringUtil.isValid(onetimeUseToken)) {           

                    String sessionToken = AuthSubUtil.exchangeForSessionToken(onetimeUseToken,null);
                    CalendarService calendarService = new CalendarService("myapp");
                    calendarService.setAuthSubToken(sessionToken, null);    
                    session.setAttribute("calendarServicesession",calendarService);
                    userIDforCalendar = (String) session.getAttribute("calendar_user_no");
                        }

                       CalendarFeed myResultsFeed1 =service.getFeed(new URL("https://www.google.com/calendar/feeds/default/allcalendars/full"),CalendarFeed.class);

            for (int i = 0; i < myResultsFeed1.getEntries().size(); i++) {
                CalendarEntry entry = myResultsFeed1.getEntries().get(i);
                           .....

}

请为我提供一些使用 CalendarService 进行离线访问的方法,这样我就不必对代码进行太多更改。 希望尽快回复。

谢谢- 德拉维特·古普塔

【问题讨论】:

    标签: java oauth google-calendar-api authsub


    【解决方案1】:

    Google 从 2012 年 4 月 20 日起弃用了 AuthSub。因此,您应该迁移到 OAuth 2.0 和 Google Calendar API v3。首先从以下链接下载 jar 文件:

    https://google-api-client-libraries.appspot.com/download/library/calendar/v3/java

    http://google-oauth-java-client.googlecode.com/files/google-oauth-java-client-1.13.1-beta.zip

    从您的项目中删除旧的日历和 Authsub jar 文件,并从此链接添加 jar 文件。

    然后转到 google api 控制台获取您的客户端 ID、客户端密码并创建重定向 uri。 并从同一个 api 控制台启用 google calendar api。

    我正在为您提供一个示例代码,该代码对用户进行身份验证并显示他拥有的日历,您必须存储您在输出中获得的刷新令牌并将其存储,以便您可以离线访问日历。

    以下函数用于 OAuth 授权。

     public void authenticate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String client_id                = "xxxx";
        String redirect_uri             = "xxxxxx";
        String scope                    = "https://www.googleapis.com/auth/calendar";
        String client_secret            = "xxxxxx";
        List <String> scopes;
        HttpTransport transport         = new NetHttpTransport();
        JsonFactory jsonFactory         = new JacksonFactory();
    
        scopes = new LinkedList<String>();
        scopes.add(scope);
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(transport, jsonFactory, client_id, client_secret, scopes).build();
        GoogleAuthorizationCodeRequestUrl url = flow.newAuthorizationUrl();
        url.setRedirectUri(redirect_uri);
        url.setApprovalPrompt("force");
        url.setAccessType("offline");
        String authorize_url = url.build();
        response.sendRedirect(authorize_url);
    }
    

    您必须为变量client_idclient_secretredirect_uri 添加值。所有这些值都在您的 google api 控制台中。

    授权函数将我转发到授权 url,它给了我一个访问令牌和一个刷新令牌。但是,访问令牌会在一段时间后过期。因此,如果您想要访问令牌,则需要存储刷新令牌并在您访问日历 API 时使用它生成它。

    以下函数生成访问令牌和刷新令牌,并打印用户谷歌日历中的日历列表。

    public void importCalendarList(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        HttpSession session = request.getSession();
        String staffKey = (String) session.getAttribute("staffKey");
        ContactJdo staffDetails = staff.getStaffDetail(staffKey);
        String code = request.getParameter("code");
        String calendarId="";
    
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(transport, jsonFactory, client_id, client_secret, scopes).build();
        GoogleTokenResponse res = flow.newTokenRequest(code).setRedirectUri(redirect_uri).execute();
        String refreshToken = res.getRefreshToken();
        String accessToken = res.getAccessToken();
    
        List <CalendarListEntry>list1= getCalendars(accessToken);
    
        for(CalendarListEntry temp:list1) {
            System.out.println(temp.getId());
        }}
    

    如果您查看上述函数,它会生成访问令牌和刷新令牌。如果您想再次生成访问令牌,请使用此功能:

    public static String getAccessToken(String refreshToken, String client_id, String client_secret) throws IOException {
        HttpTransport transport         = new NetHttpTransport();
        JsonFactory jsonFactory         = new JacksonFactory();
    
        GoogleRefreshTokenRequest req = new GoogleRefreshTokenRequest(transport, jsonFactory, refreshToken, client_id, client_secret);
        GoogleTokenResponse res = req.execute();
        String accessToken = res.getAccessToken();
        return accessToken;
    }
    

    将刷新令牌存储在某处,您可以执行日历文档中提到的所有操作。在这里找到它

    https://google-api-client-libraries.appspot.com/documentation/calendar/v3/java/latest/index.html

    【讨论】:

    • 但是如果用户已经做了这样的授权呢?如果我只有 accessToken (+ appToken + appSecret) 怎么办? v3可以吗?您的 getCalendars 方法是如何实现的?
    • 啊,看起来应该这样:GoogleCredential credential = new GoogleCredential().setAccessToken("atoken"); client = new Calendar.Builder(new NetHttpTransport(), new JacksonFactory(), credential) .setApplicationName(APPLICATION_NAME) .build(); -> groups.google.com/forum/#!topic/google-api-java-client/…
    • 是的,这有效 + 我必须在 google 控制台中启用日历 API + 以下 maven 部门:&lt;dependency&gt; &lt;groupId&gt;com.google.apis&lt;/groupId&gt; &lt;artifactId&gt;google-api-services-calendar&lt;/artifactId&gt; &lt;version&gt;v3-rev47-1.15.0-rc&lt;/version&gt; &lt;/dependency&gt; &lt;dependency&gt; &lt;groupId&gt;com.google.api-client&lt;/groupId&gt; &lt;artifactId&gt;google-api-client&lt;/artifactId&gt; &lt;version&gt;1.15.0-rc&lt;/version&gt; &lt;groupId&gt;com.google.http-client&lt;/groupId&gt; &lt;artifactId&gt;google-http-client-jackson2&lt;/artifactId&gt;
    • getCalendars 方法私有 List getCalendars(String accessToken) throws IOException{ Calendar calendarService = AppointmentUtilities.getCalendar(accessToken); Calendar.CalendarList.List list = calendarService.calendarList().list(); list.setOauthToken(accessToken);返回 list.execute().getItems();对于您的第一个问题,当我们使用离线模式时,刷新令牌会派上用场,因为访问令牌已过期。如果您想再次访问,您需要使用刷新令牌生成访问令牌
    猜你喜欢
    • 2014-05-22
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多