如何在Spring Boot中为微软工作账户实现Outlook日历同步鉴权?
在Spring Boot中实现Outlook日历同步的鉴权流程(获取Access/Refresh Token)
一、Azure AD应用注册(前置步骤)
- 登录Azure门户,注册新的"应用注册":
- 账户类型选择"任何组织目录中的账户和个人Microsoft账户"(覆盖Outlook个人用户)
- 设置重定向URI:选择"Web"类型,填入你的应用回调地址,比如
http://localhost:8080/outlook/callback
- 配置API权限:
- 点击"API权限" -> "添加权限" -> 选择"Microsoft Graph" -> "委托权限"
- 搜索并勾选
Calendars.ReadWrite(用于读写日历)和offline_access(用于获取Refresh Token) - 个人账户用户授权时自行确认,企业账户需管理员同意
- 开启授权代码流:
- 进入"认证" -> "高级设置",确保"授权代码流"已勾选(默认通常开启)
- 记录应用的
客户端ID和客户端密钥(在"证书和密码"中生成客户端密钥)
二、Spring Boot项目配置
1. 添加依赖
在pom.xml中加入以下依赖:
<!-- Spring OAuth2 Client --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <!-- Microsoft Graph SDK --> <dependency> <groupId>com.microsoft.graph</groupId> <artifactId>microsoft-graph</artifactId> <version>6.3.0</version> </dependency>
2. 配置OAuth2客户端
在application.yml中添加配置:
spring: security: oauth2: client: registration: microsoft: client-id: 你的Azure应用客户端ID client-secret: 你的Azure应用客户端密钥 scope: Calendars.ReadWrite, offline_access redirect-uri: "{baseUrl}/outlook/callback" authorization-grant-type: authorization_code provider: microsoft: authorization-uri: https://login.microsoftonline.com/common/oauth2/v2.0/authorize token-uri: https://login.microsoftonline.com/common/oauth2/v2.0/token user-info-uri: https://graph.microsoft.com/v1.0/me user-name-attribute: id
三、构建鉴权API(独立于现有登录流程)
1. Security配置
调整Spring Security,确保仅已登录(通过你的现有方案)的用户能访问Outlook鉴权接口:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/outlook/**").authenticated() .anyRequest().permitAll() ) .oauth2Client(Customizer.withDefaults()); return http.build(); } }
2. 鉴权Controller实现
创建处理授权引导和回调的接口,将Token与现有用户关联存储:
@RestController @RequestMapping("/outlook") public class OutlookAuthController { private final OAuth2AuthorizedClientService authorizedClientService; private final OAuth2AuthorizationRequestResolver authorizationRequestResolver; public OutlookAuthController(OAuth2AuthorizedClientService authorizedClientService, OAuth2AuthorizationRequestResolver authorizationRequestResolver) { this.authorizedClientService = authorizedClientService; this.authorizationRequestResolver = authorizationRequestResolver; } // 引导用户跳转到Outlook授权页面 @GetMapping("/authorize") public RedirectView authorize(HttpServletRequest request, @RequestParam String userId) { OAuth2AuthorizationRequest authRequest = authorizationRequestResolver.resolve(request, "microsoft"); return new RedirectView(authRequest.getAuthorizationUri()); } // 处理Outlook授权回调,获取Token @GetMapping("/callback") public ResponseEntity<String> callback(HttpServletRequest request, @RequestParam String code, @RequestParam String state) { // 替换为你的现有登录逻辑获取用户ID String userId = (String) request.getSession().getAttribute("userId"); OAuth2AuthorizedClient authorizedClient = authorizedClientService.loadAuthorizedClient("microsoft", userId); OAuth2AccessTokenResponse tokenResponse = authorizedClient.getAccessTokenResponse(); String accessToken = tokenResponse.getAccessToken().getTokenValue(); String refreshToken = tokenResponse.getRefreshToken().getTokenValue(); // 替换为你的实际存储逻辑,将Token与用户绑定 saveTokensToDatabase(userId, accessToken, refreshToken); return ResponseEntity.ok("Outlook授权成功,Token已保存"); } private void saveTokensToDatabase(String userId, String accessToken, String refreshToken) { // 示例:写入用户表的对应字段 } }
四、关键注意事项
- 必须包含
offline_accessscope:只有添加这个权限,才能获取Refresh Token,避免Access Token过期后需用户重新授权。 - Token与用户绑定:每个用户的Token独立,必须关联你的应用内用户ID,防止混淆。
- Refresh Token续期:当Access Token过期时,调用Azure的Token接口,用Refresh Token换取新的Access Token。
- MS Graph API调用示例:
GraphServiceClient graphClient = GraphServiceClient.builder() .authenticationProvider(request -> { request.addHeader("Authorization", "Bearer " + accessToken); return CompletableFuture.completedFuture(null); }) .buildClient();
内容的提问来源于stack exchange,提问作者deathByChocolate
相关产品推荐
相关产品推荐

