Spring Boot 社交登录和 Google 日历 API

pio*_*b86 3 google-calendar-api google-oauth spring-boot spring-security-oauth2 google-signin

问题

通过 Spring Security OAuth2 重用最终用户 Google 身份验证来访问 Web 应用程序中的 Google Calendar API

描述

我能够通过 Spring Security 登录创建一个小型 Spring Boot Web 应用程序

应用程序.yaml

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: <id>
            client-secret: <secret>
            scope:
              - email
              - profile
              - https://www.googleapis.com/auth/calendar.readonly
Run Code Online (Sandbox Code Playgroud)

当应用程序启动时,我可以访问http://localhost:8080/user并要求用户登录谷歌。成功登录后,配置文件 json 将作为以下响应显示在浏览器中:

安全控制器

@RestController
class SecurityController {
    @RequestMapping("/user")
    fun user(principal: Principal): Principal {
        return principal
    }
}
Run Code Online (Sandbox Code Playgroud)

安全配置.kt

@Configuration
class SecurityConfiguration : WebSecurityConfigurerAdapter() {
    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2Login()
    }
}
Run Code Online (Sandbox Code Playgroud)

问题

我想重用此身份验证来检索所有用户的日历事件。以下代码取自谷歌有关访问日历API的教程,但它创建了一个完全独立的授权流程并要求用户登录。

    @Throws(IOException::class)
    private fun getCredentials(httpTransport: NetHttpTransport): Credential {
        val clientSecrets = loadClientSecrets()
        return triggerUserAuthorization(httpTransport, clientSecrets)
    }

    private fun loadClientSecrets(): GoogleClientSecrets {
        val `in` = CalendarQuickstart::class.java.getResourceAsStream(CREDENTIALS_FILE_PATH)
                ?: throw FileNotFoundException("Resource not found: $CREDENTIALS_FILE_PATH")
        return GoogleClientSecrets.load(JSON_FACTORY, InputStreamReader(`in`))
    }

    private fun triggerUserAuthorization(httpTransport: NetHttpTransport, clientSecrets: GoogleClientSecrets): Credential {
        val flow = GoogleAuthorizationCodeFlow.Builder(
                httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
                .setDataStoreFactory(FileDataStoreFactory(File(TOKENS_DIRECTORY_PATH)))
                .setAccessType("offline")
                .build()
        val receiver = LocalServerReceiver.Builder().setPort(8880).build()
        return AuthorizationCodeInstalledApp(flow, receiver).authorize("user")
    }
Run Code Online (Sandbox Code Playgroud)

如何重复使用已完成的身份验证来访问 Google 帐户上的最终用户日历活动?

Sta*_*mir 5

如果我理解正确的话,您重用身份验证的意思是您想要使用 Spring 为您检索的访问和刷新令牌,以便将它们用于针对 Google API 的请求。

用户身份验证详细信息可以注入到端点方法中,如下所示:

import org.springframework.security.oauth2.client.OAuth2AuthorizedClient
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class FooController(val historyService: HistoryService) {

    @GetMapping("/foo")
    fun foo(@RegisteredOAuth2AuthorizedClient("google") user: OAuth2AuthorizedClient) {
        user.accessToken
    }

}
Run Code Online (Sandbox Code Playgroud)

有了其中的详细信息,OAuth2AuthorizedClient您应该能够使用 google API 执行您需要的任何操作。

如果您需要在没有用户向您的服务发出请求的情况下访问 API,您可以注入OAuth2AuthorizedClientService托管组件,并按如下方式使用它:

import org.springframework.security.oauth2.client.OAuth2AuthorizedClient
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService
import org.springframework.stereotype.Service

@Service
class FooService(val clientService: OAuth2AuthorizedClientService) {

    fun foo() {
        val user = clientService.loadAuthorizedClient<OAuth2AuthorizedClient>("google", "principal-name")
        user.accessToken
    }

}
Run Code Online (Sandbox Code Playgroud)