如何从应用程序访问日历而不需要询问电子邮件帐户和密码?

Posted

技术标签:

【中文标题】如何从应用程序访问日历而不需要询问电子邮件帐户和密码?【英文标题】:How to access calendars from an application without needed to ask for email account and password? 【发布时间】:2021-09-11 13:18:37 【问题描述】:

我想开发一个应用程序来访问谷歌帐户中的一些日历。

我的想法是只设置谷歌帐户 myaccount@gmail.com 并且应用程序可以连接。唯一的要求是访问 google 帐户并授予对我的应用程序的访问权限。通过这种方式,我可以为许多用户安装应用程序,而他们不需要做任何事情。

这就是插件caldav synchronizer 的工作原理。

为此,我在我的 google 帐户中创建了一个服务帐户,并使用此代码尝试创建日历服务:

public CalendarService GetCalendarServiceServiceAccount(string paramStrPathCertificado, string paramStrEmailServiceAccount, string[] paramScopes)

    var certificate = new X509Certificate2(paramStrPathCertificado, "notasecret", X509KeyStorageFlags.Exportable);

    ServiceAccountCredential credential = new ServiceAccountCredential(
        new ServiceAccountCredential.Initializer(paramStrEmailServiceAccount)
            
                Scopes = paramScopes,
            .FromCertificate(certificate));


    CalendarService micalendarService = new CalendarService(new BaseClientService.Initializer()
        
            HttpClientInitializer = credential,
            ApplicationName = "My Calendars"
        );

        return micalendarService;

然后要获取我使用此代码的日历:

var dummyService = GetCalendarServiceServiceAccount("credentials2.p12", "myCalendars@XXX.gserviceaccount.com", ScopesParaModificar);
IEnumerable<CalendarListEntry> dummyCalendarios = dummyService.CalendarList.List().Execute().Items;

以及范围:

static string[] ScopesParaModificar =  CalendarService.Scope.Calendar, CalendarService.Scope.CalendarEvents ;

问题是我没有日历。

In this question,答案说在我的google账户中,我应该将服务账户的用户添加到我的日历中,但是它不起作用,我无法获取日历。这个解决方案也不是我真正想要的,因为我不想将此服务帐户添加到我的日历中。在 caldav 同步器中,我不需要添加日历的任何用户,只需将具有日历的谷歌帐户设置为用户,然后允许应用程序作为受信任的应用程序。

那么我怎样才能访问我的日历,只说明我的谷歌帐户并授予应用程序权限?

谢谢。

【问题讨论】:

【参考方案1】:

与服务帐号共享

为了让服务帐户访问日历。日历的所有者,通常是应用程序的开发者。将获取服务帐户电子邮件地址并与服务帐户共享日历。这是通过 Web ui 完成的,就像您对任何其他用户一样。

与服务帐户共享日历后,它将能够访问它。

什么是日历列表。

CalendarList.List 用于请求用户添加到其 CalendarList 的日历列表。日历列表只是 google 日历 Web 应用程序中的一个 UI 元素。它显示在 Google 日历网络用户界面的左下方

在 Google 日历 Web 应用程序中,当您创建新日历时,它会自动添加用户日历列表。如果与您共享日历,则通常也会在其中添加日历。 (我发现这是错误的)

但是,如果您与服务帐户共享日历,因为它没有 UI 元素,它们不会自动添加。这就是服务帐户 calendarlist.list 返回空的原因。

如果您想将日历添加到服务帐户日历列表,则需要执行 calendarlist.insert 并手动添加。

你应该做什么。

我想开发一个应用程序来访问谷歌帐户中的一些日历。

谁拥有您要访问的日历。如果是您,那么您应该使用服务帐户。

如果日历归其他用户所有,那么您将需要使用 Oauth2 并授权用户访问他们的数据,您不应在此用例中使用服务帐户。使用 Oauth2 让您的用户授权您的应用程序存储刷新令牌,然后在将来使用刷新令牌访问他们的日历。

【讨论】:

感谢您的解释。但我仍有疑问。在 caldav 插件中,我在用户中安装插件。在同步器中,我只需提供日历所有者的电子邮件,然后转到日历所有者的帐户并授予对插件的访问权限。但我必须这样做一次,然后我可以安装给另一个用户,只需给他日历所有者的电子邮件,我就可以访问日历。所以我不需要与 Google 服务共享日历。 无法告诉您插件是如何工作的,您可以尝试联系所有者并询问他们。我只能告诉你google calendar api是如何工作的。 "如果您想将日历添加到服务帐户日历列表,则需要执行 calendarlist.insert 并手动添加。"我怎么能做手动插入?我必须创建一个应用程序来连接到 canledear 的所有者帐户并在服务帐户中插入? 您不能手动添加它,您需要使用 calendarlist.insert 方法手动添加。在您的应用程序中为他们创建一个端点,他们可以在其中添加它。如果您不是此帐户的所有者,则不应使用服务帐户。 最后一节中提到的 OAuth2 可能会造成混淆,因为使用服务帐户进行授权也被视为 OAuth2,尽管它是 2-legged 而不是 3-legged developers.google.com/identity/protocols/oauth2/service-account。我建议编辑掉这些提及。

以上是关于如何从应用程序访问日历而不需要询问电子邮件帐户和密码?的主要内容,如果未能解决你的问题,请参考以下文章

使用来自单个域管理员帐户的O365 REST API访问其他用户日历

如何从单个谷歌帐户的多个谷歌日历中获取所有事件?

将 Mandrill 帐户合并到 Mailchimp 后,如果我的发送域未设置为接收电子邮件,我该如何接受验证电子邮件?

带有 EKEvents 的 PromiseKit - 询问用户访问日历事件的权限

从 Google 服务帐户编辑 Google 日历事件:403

同步到交换帐户时,iOS 无法更新日历事件