如何将Spring Boot Java应用程序与MS个人帐户用户的Outlook日历集成



我们的想法是构建一个Spring Boot Java应用程序,用它我们可以获取MS Outlook个人帐户持有人的日历数据,比如即将发生的事件。基于最初的研究,我发现MS-Graph API是同样的答案,我从本教程开始作为一个启动代码。

我的application.yml文件如下:

spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id: common
credential:
client-id: <from azure portal>
client-secret: <from azure portal>
authorization-clients:
graph:
scopes:
- https://graph.microsoft.com/User.Read
- https://graph.microsoft.com/Calendars.Read
- https://graph.microsoft.com/Calendars.ReadWrite
- https://graph.microsoft.com/Analytics.Read

租户id设置为通用,因为我想与任何个人展望账户持有人连接。在Azure门户网站上,支持的帐户类型设置为"-";任何组织目录中的帐户(任何Azure AD目录-多租户(和个人Microsoft帐户(例如Skype、Xbox(">在此处输入图像描述

为了测试我是否可以访问MS-Graph日历API,我添加了下面提到的代码(来自这里(:

EventCollectionPage events = graphClient.me().calendar().events()
.buildRequest()
.get();

我可以连接到Outlook日历,并为我自己的帐户获取事件,该帐户恰好与访问Azure门户的帐户相同。因此,我的个人账户abcXyz@outlook.com也是注册应用程序的租户的管理员帐户。

但是,当我试图连接到另一个由我创建的个人展望帐户时,我在相关日历中添加了一些事件以进行测试,但我失败了。这个新的outlook个人帐户肯定不在应用程序注册的租户中,我不太确定个人MS帐户进入哪个租户,以及如何向他们添加服务主体。

在为azure门户网站上的所有帐户配置应用程序注册并使租户id在我的application.yml文件中通用后,我原本希望连接所有注册Java应用程序的个人帐户,但遇到了以下错误。微软身份平台似乎不允许其他用户将其日历连接到我的Java应用程序,因为我的应用程序的服务主体没有存储在个人帐户持有人的租户中但是怎么做呢我解决问题的方法是正确的吗?或者我应该不利用Spring库(OAuth2Client、AzureActiveDirectory(而更喜欢自己构建OAuth2.0客户端,自己访问/authorize和/token端点,尽管MS不建议这样做,如前所述

java.lang.IllegalArgumentException: Missing attribute 'name' in attributes
at org.springframework.security.oauth2.core.user.DefaultOAuth2User.<init>(DefaultOAuth2User.java:72) ~[spring-security-oauth2-core-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser.<init>(DefaultOidcUser.java:93) ~[spring-security-oauth2-core-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser.<init>(DefaultOidcUser.java:67) ~[spring-security-oauth2-core-5.6.7.jar:5.6.7]
at com.azure.spring.cloud.autoconfigure.aad.implementation.webapp.AadOAuth2UserService.loadUser(AadOAuth2UserService.java:134) ~[spring-cloud-azure-autoconfigure-4.3.0.jar:4.3.0]
at com.azure.spring.cloud.autoconfigure.aad.implementation.webapp.AadOAuth2UserService.loadUser(AadOAuth2UserService.java:52) ~[spring-cloud-azure-autoconfigure-4.3.0.jar:4.3.0]
at org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider.authenticate(OidcAuthorizationCodeAuthenticationProvider.java:156) ~[spring-security-oauth2-client-5.6.7.jar:5.6.7]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:195) ~[spring-security-oauth2-client-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:223) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:178) ~[spring-security-oauth2-client-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186) ~[spring-security-web-5.6.7.jar:5.6.7]

spring-cloud-azure-starter-active-directory旨在支持Work/School account。是否支持Personal account目前还不确定。在本期GitHub中对其进行了跟踪。

关于Work/School accountPersonal account之间的差异,请参阅本页。

使用此示例学习如何调用图

个人是其个人帐户的管理员。当他们登录到你的应用程序时,会有一个操作列表,在他们使用你的应用之前,他们需要同意这些操作。在你的情况下,其中一个会像";阅读日历"然后,个人将授予您的应用程序读取其展望日历的能力。希望这能帮助维亚萨。

最新更新