# 核心配置
# Spring 启动 2.x 示例
Spring Boot2.x 为 OAuth2.0 登录带来了完整的自动配置功能。
本节展示如何使用谷歌作为身份验证提供者配置**OAuth2.0 登录 WebFlux 样本 ** (opens new window),并涵盖以下主题:
# 初始设置
要使用 Google 的 OAuth2.0 身份验证系统进行登录,你必须在 Google API 控制台中设置一个项目,以获得 OAuth2.0 凭据。
用于身份验证的谷歌的 OAuth2.0 实现 (opens new window)符合OpenID Connect1.0 (opens new window)规范,并且是OpenID 认证 (opens new window)。 |
---|
按照OpenID 连接 (opens new window)页面上的说明,从“设置 OAuth2.0”一节开始。
在完成“获取 OAuth2.0 凭据”说明之后,你应该有一个新的 OAuth 客户机,其凭据由一个客户机 ID 和一个客户机秘密组成。
# 设置重定向 URI
重定向 URI 是应用程序中的路径,终端用户的用户代理在与 Google 进行身份验证并授予对同意页面上的 OAuth 客户端 (在前一步中创建) 的访问权限后,会被重定向回应用程序中的路径。
在“设置重定向 URI”子节中,确保将授权重定向 URI字段设置为[http://localhost:8080/login/oauth2/code/google](http://localhost:8080/login/oauth2/code/google)
。
默认的重定向 URI 模板是{baseUrl}/login/oauth2/code/{registrationId} 。***注册 ID***是客户登记的唯一标识符。 对于我们的示例, registrationId 是google 。 |
---|
如果 OAuth 客户端运行在代理服务器后面,建议检查代理服务器配置以确保应用程序配置正确。 此外,请参阅支持的[ URI 模板变量](../client/Authorization-grants.html#OAuth2client-auth-code-redirect-uri)。 |
---|
# 配置application.yml
现在,你有了一个新的 OAuth 客户机和 Google,你需要将应用程序配置为使用认证流程的 OAuth 客户机。这样做:
转到
application.yml
并设置以下配置:spring: security: oauth2: client: registration: (1) google: (2) client-id: google-client-id client-secret: google-client-secret
例 1。OAuth 客户属性
1 spring.security.oauth2.client.registration
是 OAuth 客户机属性的基本属性前缀。2 在基本属性前缀之后是[ ClientRegistration
](../client/core.html#OAuth2client-client-registration)的 ID,例如 Google。用前面创建的 OAuth2.0 凭据替换
client-id
和client-secret
属性中的值。
# 启动应用程序
启动 Spring boot2.x 示例,然后转到[http://localhost:8080](http://localhost:8080)
。然后,你将被重定向到默认的自动生成登录页面,该页面显示了 Google 的链接。
点击谷歌链接,然后你将被重定向到谷歌进行身份验证。
在使用谷歌帐户凭据进行身份验证后,显示给你的下一页是“同意”屏幕。同意屏幕要求你允许或拒绝访问你之前创建的 OAuth 客户端。单击允许授权 OAuth 客户端访问你的电子邮件地址和基本配置文件信息。
此时,OAuth 客户机从用户信息端点 (opens new window)检索你的电子邮件地址和基本配置文件信息,并建立经过身份验证的会话。
# Spring 启动 2.x 属性映射
下表概述了 Spring Boot2.x OAuth 客户机属性到客户登记属性的映射。
Spring 启动 2.x | 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 提供者的配置端点 (opens new window)或授权服务器的元数据端点 (opens new window)来初始配置ClientRegistration 。 |
---|
# 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 )匹配GOOGLE``enum (不区分大小写)中的CommonOAuth2Provider 。 |
---|
对于可能希望指定不同的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() 中设置的客户机属性的自动违约。 |
# 配置自定义提供程序属性
有一些 OAuth2.0 提供程序支持多租赁,这会导致每个租户(或子域)的协议端点不同。
例如,向 OKTA 注册的 OAuth 客户端被分配到特定的子域并具有自己的协议端点。
对于这些情况, Spring Boot2.x 为配置自定义提供程序属性提供了以下基本属性: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 启动 2.x 自动配置
OAuth 客户端支持的 Spring Boot2.x 自动配置类是ReactiveOAuth2ClientAutoConfiguration
。
它执行以下任务:
从配置的 OAuth 客户机属性中寄存器
ReactiveClientRegistrationRepository``@Bean
组成的ClientRegistration
。注册
SecurityWebFilterChain``@Bean
并通过serverHttpSecurity.oauth2Login()
启用 OAuth2.0 登录。
如果需要根据你的特定需求重写自动配置,可以通过以下方式执行:
# Register a ReactiveClientRegistrationRepository @Bean
下面的示例显示了如何注册ReactiveClientRegistrationRepository``@Bean
:
爪哇
@Configuration
public class OAuth2LoginConfig {
@Bean
public ReactiveClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryReactiveClientRegistrationRepository(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();
}
}
Kotlin
@Configuration
class OAuth2LoginConfig {
@Bean
fun clientRegistrationRepository(): ReactiveClientRegistrationRepository {
return InMemoryReactiveClientRegistrationRepository(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://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()
}
}
# Register a SecurityWebFilterChain @Bean
下面的示例显示了如何用@EnableWebFluxSecurity
注册SecurityWebFilterChain``@Bean
并通过serverHttpSecurity.oauth2Login()
启用 OAuth2.0 登录:
例 2。OAuth2 登录配置
爪哇
@EnableWebFluxSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(authorize -> authorize
.anyExchange().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
}
Kotlin
@EnableWebFluxSecurity
class OAuth2LoginSecurityConfig {
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2Login { }
}
}
}
# 完全覆盖自动配置
下面的示例展示了如何通过注册一个ReactiveClientRegistrationRepository``@Bean
和一个SecurityWebFilterChain``@Bean
来完全覆盖自动配置。
例 3。覆盖自动配置
爪哇
@EnableWebFluxSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(authorize -> authorize
.anyExchange().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ReactiveClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryReactiveClientRegistrationRepository(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();
}
}
Kotlin
@EnableWebFluxSecurity
class OAuth2LoginConfig {
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2Login { }
}
}
@Bean
fun clientRegistrationRepository(): ReactiveClientRegistrationRepository {
return InMemoryReactiveClientRegistrationRepository(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://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 boot2.x 的 爪哇 配置
如果你不能使用 Spring Boot2.x,并且希望在CommonOAuth2Provider
中配置一个预定义的提供程序(例如,Google),请应用以下配置:
例 4。OAuth2 登录配置
Java
@EnableWebFluxSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(authorize -> authorize
.anyExchange().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ReactiveClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryReactiveClientRegistrationRepository(this.googleClientRegistration());
}
@Bean
public ReactiveOAuth2AuthorizedClientService authorizedClientService(
ReactiveClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public ServerOAuth2AuthorizedClientRepository authorizedClientRepository(
ReactiveOAuth2AuthorizedClientService authorizedClientService) {
return new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService);
}
private ClientRegistration googleClientRegistration() {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build();
}
}
Kotlin
@EnableWebFluxSecurity
class OAuth2LoginConfig {
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2Login { }
}
}
@Bean
fun clientRegistrationRepository(): ReactiveClientRegistrationRepository {
return InMemoryReactiveClientRegistrationRepository(googleClientRegistration())
}
@Bean
fun authorizedClientService(
clientRegistrationRepository: ReactiveClientRegistrationRepository
): ReactiveOAuth2AuthorizedClientService {
return InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository)
}
@Bean
fun authorizedClientRepository(
authorizedClientService: ReactiveOAuth2AuthorizedClientService
): ServerOAuth2AuthorizedClientRepository {
return AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService)
}
private fun googleClientRegistration(): ClientRegistration {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build()
}
}
← OAuth2.0 登录 高级配置 →