跳到主要内容
版本:6.4.3

核心配置

QWen Max 中英对照 Core Configuration

Spring Boot 示例​

Spring Boot 为 OAuth 2.0 登录带来了完整的自动配置功能。

本节展示如何使用 Google 作为 身份提供商 来配置 OAuth 2.0 登录示例,涵盖以下主题:

初始设置​

要使用 Google 的 OAuth 2.0 身份验证系统进行登录,您必须在 Google API 控制台中设置一个项目以获取 OAuth 2.0 凭据。

备注

Google 的 OAuth 2.0 实现 用于身份验证,符合 OpenID Connect 1.0 规范,并且是 OpenID 认证 的。

请按照 OpenID Connect 页面上的说明操作,从“设置 OAuth 2.0”部分开始。

在完成“获取 OAuth 2.0 凭据”的说明后,你应该会有一个新的 OAuth 客户端,其凭据包括一个客户端 ID 和一个客户端密钥。

设置重定向 URI​

重定向 URI 是应用程序中的路径,终端用户的用户代理在他们通过 Google 进行身份验证并在同意页面上授予对 OAuth 客户端(在上一步中创建)的访问权限后会被重定向到该路径。

在“设置重定向 URI”小节中,确保 Authorized redirect URIs 字段设置为 [localhost:8080/login/oauth2/code/google](http://localhost:8080/login/oauth2/code/google)。

提示

默认的重定向 URI 模板是 {baseUrl}/login/oauth2/code/{registrationId}。registrationId 是 ClientRegistration 的唯一标识符。

important

如果 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
    • spring.security.oauth2.client.registration 是 OAuth 客户端属性的基本属性前缀。

    • 在基本属性前缀之后是 ClientRegistration 的 ID,例如 Google。

  2. 用你之前创建的 OAuth 2.0 凭据替换 client-id 和 client-secret 属性中的值。

启动应用程序​

启动 Spring Boot 示例并访问 localhost:8080。然后你将被重定向到默认的自动生成的登录页面,该页面上显示了一个 Google 的链接。

点击 Google 链接,然后你将被重定向到 Google 进行认证。

使用您的 Google 帐号凭据进行身份验证后,您会看到“同意屏幕”。同意屏幕会询问您是允许还是拒绝访问您之前创建的 OAuth 客户端。点击允许以授权 OAuth 客户端访问您的电子邮件地址和基本个人资料信息。

此时,OAuth 客户端从 UserInfo Endpoint 获取您的电子邮件地址和基本个人资料信息,并建立一个已认证的会话。

Spring Boot 属性映射​

下表概述了 Spring Boot OAuth 客户端属性到 ClientRegistration 属性的映射。

Spring BootClientRegistration
spring.security.oauth2.client.registration._[registrationId]_registrationId
spring.security.oauth2.client.registration._[registrationId]_.client-idclientId
spring.security.oauth2.client.registration._[registrationId]_.client-secretclientSecret
spring.security.oauth2.client.registration._[registrationId]_.client-authentication-methodclientAuthenticationMethod
spring.security.oauth2.client.registration._[registrationId]_.authorization-grant-typeauthorizationGrantType
spring.security.oauth2.client.registration._[registrationId]_.redirect-uriredirectUri
spring.security.oauth2.client.registration._[registrationId]_.scopescopes
spring.security.oauth2.client.registration._[registrationId]_.client-nameclientName
spring.security.oauth2.client.provider._[providerId]_.authorization-uriproviderDetails.authorizationUri
spring.security.oauth2.client.provider._[providerId]_.token-uriproviderDetails.tokenUri
spring.security.oauth2.client.provider._[providerId]_.jwk-set-uriproviderDetails.jwkSetUri
spring.security.oauth2.client.provider._[providerId]_.issuer-uriproviderDetails.issuerUri
spring.security.oauth2.client.provider._[providerId]_.user-info-uriproviderDetails.userInfoEndpoint.uri
spring.security.oauth2.client.provider._[providerId]_.user-info-authentication-methodproviderDetails.userInfoEndpoint.authenticationMethod
spring.security.oauth2.client.provider._[providerId]_.user-name-attributeproviderDetails.userInfoEndpoint.userNameAttributeName
提示

你可以通过发现 OpenID Connect 提供者的配置端点或授权服务器的元数据端点来初始配置一个 ClientRegistration,方法是指定 spring.security.oauth2.client.provider._[providerId]_.issuer-uri 属性。

CommonOAuth2Provider​

CommonOAuth2Provider 预定义了一组针对一些知名提供商的默认客户端属性:Google、GitHub、Facebook 和 Okta。

例如,authorization-uri、token-uri 和 user-info-uri 对于提供商来说不经常更改。因此,提供默认值以减少所需的配置是有意义的。

正如前面所演示的,当我们配置 Google 客户端时,只需要 client-id 和 client-secret 属性。

以下列表展示了一个示例:

spring:
security:
oauth2:
client:
registration:
google:
client-id: google-client-id
client-secret: google-client-secret
提示

客户端属性的自动默认设置在这里无缝工作,因为 registrationId(google)与 CommonOAuth2Provider 中的 GOOGLE 枚举(不区分大小写)匹配。

对于您可能想要指定不同的 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
  • registrationId 被设置为 google-login。

  • 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
  • 基础属性(spring.security.oauth2.client.provider.okta)允许自定义协议端点位置的配置。

覆盖 Spring Boot 自动配置​

Spring Boot 的 OAuth 客户端支持的自动配置类是 OAuth2ClientAutoConfiguration。

它执行以下任务:

  • 注册一个由配置的 OAuth 客户端属性中的 ClientRegistration 组成的 ClientRegistrationRepository @Bean。

  • 注册一个 SecurityFilterChain @Bean,并通过 httpSecurity.oauth2Login() 启用 OAuth 2.0 登录。

如果你需要根据你的特定需求覆盖自动配置,你可以通过以下方式进行:

注册一个 ClientRegistrationRepository @Bean​

以下示例展示了如何注册一个 ClientRegistrationRepository @Bean:

@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://accounts.google.com/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 登录:

@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {

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

完全覆盖自动配置​

以下示例展示了如何通过注册 ClientRegistrationRepository @Bean 和 SecurityFilterChain @Bean 来完全覆盖自动配置。

@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://accounts.google.com/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),请应用以下配置:

@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();
}
}