核心配置

Spring Boot 示例

Spring Boot 為 OAuth 2.0 登入帶來了完整的自動配置功能。

本節展示瞭如何使用 Google 作為身份驗證提供程式來配置OAuth 2.0 登入示例,並涵蓋以下主題:

初始設定

要使用 Google 的 OAuth 2.0 身份驗證系統進行登入,您必須在 Google API 控制檯中設定一個專案以獲取 OAuth 2.0 憑據。

請遵循 OpenID Connect 頁面上的說明,從“設定 OAuth 2.0”部分開始。

完成“獲取 OAuth 2.0 憑據”說明後,您應該會有一個新的 OAuth 客戶端,其憑據包括客戶端 ID 和客戶端金鑰。

設定重定向 URI

重定向 URI 是應用程式中的路徑,當終端使用者透過 Google 身份驗證並在同意頁面上授予對 OAuth 客戶端(在上一步中建立的)的訪問許可權後,使用者的使用者代理將重定向回該路徑。

在“設定重定向 URI”小節中,確保 授權重定向 URI 欄位設定為 localhost:8080/login/oauth2/code/google

預設的重定向 URI 模板是 {baseUrl}/login/oauth2/code/{registrationId}registrationIdClientRegistration 的唯一識別符號。

如果 OAuth 客戶端執行在代理伺服器後面,您應該檢查代理伺服器配置以確保應用程式已正確配置。另請參閱 redirect-uri 支援的 URI 模板變數

配置 application.yml

現在您擁有一個使用 Google 的新 OAuth 客戶端,您需要配置應用程式以將 OAuth 客戶端用於身份驗證流程。為此:

  1. 前往 application.yml 並設定以下配置:

    spring:
      security:
        oauth2:
          client:
            registration:	(1)
              google:	(2)
                client-id: google-client-id
                client-secret: google-client-secret
    OAuth 客戶端屬性
    1 spring.security.oauth2.client.registration 是 OAuth 客戶端屬性的基礎屬性字首。
    2 在基礎屬性字首之後是 ClientRegistration 的 ID,例如 Google。
  2. client-idclient-secret 屬性中的值替換為您之前建立的 OAuth 2.0 憑據。

啟動應用程式

啟動 Spring Boot 示例並訪問 localhost:8080。您將被重定向到預設的自動生成的登入頁面,該頁面顯示 Google 的連結。

點選 Google 連結,您將被重定向到 Google 進行身份驗證。

使用您的 Google 帳戶憑據進行身份驗證後,您會看到同意螢幕。同意螢幕會詢問您是否允許或拒絕訪問您之前建立的 OAuth 客戶端。點選 允許 以授權 OAuth 客戶端訪問您的電子郵件地址和基本個人資料資訊。

此時,OAuth 客戶端從 UserInfo Endpoint 檢索您的電子郵件地址和基本個人資料資訊,並建立經過身份驗證的會話。

Spring Boot 屬性對映

下表概述了 Spring Boot OAuth 客戶端屬性到 ClientRegistration 屬性的對映。

Spring Boot ClientRegistration

spring.security.oauth2.client.registration.[registrationId]

registrationId

spring.security.oauth2.client.registration.[registrationId].client-id

clientId

spring.security.oauth2.client.registration.[registrationId].client-secret

clientSecret

spring.security.oauth2.client.registration.[registrationId].client-authentication-method

clientAuthenticationMethod

spring.security.oauth2.client.registration.[registrationId].authorization-grant-type

authorizationGrantType

spring.security.oauth2.client.registration.[registrationId].redirect-uri

redirectUri

spring.security.oauth2.client.registration.[registrationId].scope

scopes

spring.security.oauth2.client.registration.[registrationId].client-name

clientName

spring.security.oauth2.client.provider.[providerId].authorization-uri

providerDetails.authorizationUri

spring.security.oauth2.client.provider.[providerId].token-uri

providerDetails.tokenUri

spring.security.oauth2.client.provider.[providerId].jwk-set-uri

providerDetails.jwkSetUri

spring.security.oauth2.client.provider.[providerId].issuer-uri

providerDetails.issuerUri

spring.security.oauth2.client.provider.[providerId].user-info-uri

providerDetails.userInfoEndpoint.uri

spring.security.oauth2.client.provider.[providerId].user-info-authentication-method

providerDetails.userInfoEndpoint.authenticationMethod

spring.security.oauth2.client.provider.[providerId].user-name-attribute

providerDetails.userInfoEndpoint.userNameAttributeName

您可以透過指定 spring.security.oauth2.client.provider.[providerId].issuer-uri 屬性,透過發現 OpenID Connect 提供者的 配置端點 或授權伺服器的 元資料端點 來初步配置 ClientRegistration

CommonOAuth2Provider

CommonOAuth2Provider 為許多知名提供商預定義了一組預設客戶端屬性:Google、GitHub、Facebook、X 和 Okta。

例如,提供商的 authorization-uritoken-uriuser-info-uri 不經常更改。因此,提供預設值以減少所需的配置是有意義的。

如前所示,當我們配置 Google 客戶端時,只需要 client-idclient-secret 屬性。

以下列表顯示了一個示例

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: google-client-id
            client-secret: google-client-secret
客戶端屬性的自動預設值在此處無縫工作,因為 registrationId (google) 與 CommonOAuth2Provider 中的 GOOGLE enum(不區分大小寫)匹配。

對於您可能希望指定不同 registrationId(例如 google-login)的情況,您仍然可以透過配置 provider 屬性來利用客戶端屬性的自動預設值。

以下列表顯示了一個示例

spring:
  security:
    oauth2:
      client:
        registration:
          google-login:	(1)
            provider: google	(2)
            client-id: google-client-id
            client-secret: google-client-secret
1 registrationId 設定為 google-login
2 provider 屬性設定為 google,這將利用 CommonOAuth2Provider.GOOGLE.getBuilder() 中設定的客戶端屬性的自動預設值。

配置自定義提供商屬性

有一些 OAuth 2.0 提供商支援多租戶,這導致每個租戶(或子域)都有不同的協議端點。

例如,在 Okta 中註冊的 OAuth 客戶端被分配到一個特定的子域,並擁有自己的協議端點。

對於這些情況,Spring Boot 提供了以下基礎屬性來配置自定義提供商屬性:spring.security.oauth2.client.provider.[providerId]

以下列表顯示了一個示例

spring:
  security:
    oauth2:
      client:
        registration:
          okta:
            client-id: okta-client-id
            client-secret: okta-client-secret
        provider:
          okta:	(1)
            authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
            token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
            user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo
            user-name-attribute: sub
            jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys
1 基礎屬性(spring.security.oauth2.client.provider.okta)允許自定義配置協議端點位置。

覆蓋 Spring Boot 自動配置

Spring Boot 用於 OAuth 客戶端支援的自動配置類是 OAuth2ClientAutoConfiguration

它執行以下任務:

  • 註冊一個由配置的 OAuth 客戶端屬性組成的 ClientRegistration(s) @Bean

  • 註冊一個 SecurityFilterChain @Bean 並透過 httpSecurity.oauth2Login() 啟用 OAuth 2.0 登入。

如果您需要根據您的具體要求覆蓋自動配置,您可以透過以下方式進行:

註冊一個 ClientRegistrationRepository @Bean

以下示例展示瞭如何註冊一個 ClientRegistrationRepository @Bean

  • Java

  • Kotlin

@Configuration
public class OAuth2LoginConfig {

	@Bean
	public ClientRegistrationRepository clientRegistrationRepository() {
		return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
	}

	private ClientRegistration googleClientRegistration() {
		return ClientRegistration.withRegistrationId("google")
			.clientId("google-client-id")
			.clientSecret("google-client-secret")
			.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
			.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
			.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
			.scope("openid", "profile", "email", "address", "phone")
			.authorizationUri("https://#/o/oauth2/v2/auth")
			.tokenUri("https://www.googleapis.com/oauth2/v4/token")
			.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
			.userNameAttributeName(IdTokenClaimNames.SUB)
			.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
			.clientName("Google")
			.build();
	}
}
@Configuration
class OAuth2LoginConfig {
    @Bean
    fun clientRegistrationRepository(): ClientRegistrationRepository {
        return InMemoryClientRegistrationRepository(googleClientRegistration())
    }

    private fun googleClientRegistration(): ClientRegistration {
        return ClientRegistration.withRegistrationId("google")
                .clientId("google-client-id")
                .clientSecret("google-client-secret")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
                .scope("openid", "profile", "email", "address", "phone")
                .authorizationUri("https://#/o/oauth2/v2/auth")
                .tokenUri("https://www.googleapis.com/oauth2/v4/token")
                .userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
                .userNameAttributeName(IdTokenClaimNames.SUB)
                .jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
                .clientName("Google")
                .build()
    }
}

註冊一個 SecurityFilterChain @Bean

以下示例展示瞭如何使用 @EnableWebSecurity 註冊一個 SecurityFilterChain @Bean,並透過 httpSecurity.oauth2Login() 啟用 OAuth 2.0 登入:

OAuth2 登入配置
  • Java

  • Kotlin

@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests((authorize) -> authorize
				.anyRequest().authenticated()
			)
			.oauth2Login(withDefaults());
		return http.build();
	}
}
@Configuration
@EnableWebSecurity
class OAuth2LoginSecurityConfig {

    open fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2Login { }
        }
        return http.build()
    }
}

完全覆蓋自動配置

以下示例展示瞭如何透過註冊一個 ClientRegistrationRepository @Bean 和一個 SecurityFilterChain @Bean 來完全覆蓋自動配置。

覆蓋自動配置
  • Java

  • Kotlin

@Configuration
public class OAuth2LoginConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests((authorize) -> authorize
				.anyRequest().authenticated()
			)
			.oauth2Login(withDefaults());
		return http.build();
	}

	@Bean
	public ClientRegistrationRepository clientRegistrationRepository() {
		return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
	}

	private ClientRegistration googleClientRegistration() {
		return ClientRegistration.withRegistrationId("google")
			.clientId("google-client-id")
			.clientSecret("google-client-secret")
			.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
			.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
			.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
			.scope("openid", "profile", "email", "address", "phone")
			.authorizationUri("https://#/o/oauth2/v2/auth")
			.tokenUri("https://www.googleapis.com/oauth2/v4/token")
			.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
			.userNameAttributeName(IdTokenClaimNames.SUB)
			.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
			.clientName("Google")
			.build();
	}
}
@Configuration
class OAuth2LoginConfig {

    @Bean
    open fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2Login { }
        }
        return http.build()
    }

    @Bean
    fun clientRegistrationRepository(): ClientRegistrationRepository {
        return InMemoryClientRegistrationRepository(googleClientRegistration())
    }

    private fun googleClientRegistration(): ClientRegistration {
        return ClientRegistration.withRegistrationId("google")
                .clientId("google-client-id")
                .clientSecret("google-client-secret")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
                .scope("openid", "profile", "email", "address", "phone")
                .authorizationUri("https://#/o/oauth2/v2/auth")
                .tokenUri("https://www.googleapis.com/oauth2/v4/token")
                .userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
                .userNameAttributeName(IdTokenClaimNames.SUB)
                .jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
                .clientName("Google")
                .build()
    }
}

不使用 Spring Boot 的 Java 配置

如果您無法使用 Spring Boot 並希望配置 CommonOAuth2Provider 中預定義的提供商之一(例如 Google),請應用以下配置:

OAuth2 登入配置
  • Java

  • Kotlin

  • Xml

@Configuration
@EnableWebSecurity
public class OAuth2LoginConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.authorizeHttpRequests((authorize) -> authorize
				.anyRequest().authenticated()
			)
			.oauth2Login(withDefaults());
		return http.build();
	}

	@Bean
	public ClientRegistrationRepository clientRegistrationRepository() {
		return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
	}

	@Bean
	public OAuth2AuthorizedClientService authorizedClientService(
			ClientRegistrationRepository clientRegistrationRepository) {
		return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
	}

	@Bean
	public OAuth2AuthorizedClientRepository authorizedClientRepository(
			OAuth2AuthorizedClientService authorizedClientService) {
		return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
	}

	private ClientRegistration googleClientRegistration() {
		return CommonOAuth2Provider.GOOGLE.getBuilder("google")
			.clientId("google-client-id")
			.clientSecret("google-client-secret")
			.build();
	}
}
@Configuration
@EnableWebSecurity
open class OAuth2LoginConfig {
    @Bean
    open fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }
            oauth2Login { }
        }
        return http.build()
    }

    @Bean
    open fun clientRegistrationRepository(): ClientRegistrationRepository {
        return InMemoryClientRegistrationRepository(googleClientRegistration())
    }

    @Bean
    open fun authorizedClientService(
        clientRegistrationRepository: ClientRegistrationRepository?
    ): OAuth2AuthorizedClientService {
        return InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository)
    }

    @Bean
    open fun authorizedClientRepository(
        authorizedClientService: OAuth2AuthorizedClientService?
    ): OAuth2AuthorizedClientRepository {
        return AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)
    }

    private fun googleClientRegistration(): ClientRegistration {
        return CommonOAuth2Provider.GOOGLE.getBuilder("google")
            .clientId("google-client-id")
            .clientSecret("google-client-secret")
            .build()
    }
}
<http auto-config="true">
	<intercept-url pattern="/**" access="authenticated"/>
	<oauth2-login authorized-client-repository-ref="authorizedClientRepository"/>
</http>

<client-registrations>
	<client-registration registration-id="google"
						 client-id="google-client-id"
						 client-secret="google-client-secret"
						 provider-id="google"/>
</client-registrations>

<b:bean id="authorizedClientService"
		class="org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService"
		autowire="constructor"/>

<b:bean id="authorizedClientRepository"
		class="org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository">
	<b:constructor-arg ref="authorizedClientService"/>
</b:bean>
© . This site is unofficial and not affiliated with VMware.