# 核心配置
# Spring 启动2.x示例
Spring Boot2.x为OAuth2.0登录带来了完整的自动配置功能。
本节展示如何使用谷歌作为身份验证提供者配置OAuth2.0登录示例 (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)。 |
---|
从“设置OAuth2.0”一节开始,按照OpenID连接 (opens new window)页面上的说明进行操作。
在完成“获取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***是客户登记的唯一标识符。 |
---|
如果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 在基本属性前缀之后是客户登记的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自动配置类是OAuth2ClientAutoConfiguration
。
它执行以下任务:
从配置的OAuth客户机属性中寄存器
ClientRegistrationRepository``@Bean
组成的ClientRegistration
。提供
WebSecurityConfigurerAdapter``@Configuration
并通过httpSecurity.oauth2Login()
启用OAuth2.0登录。
如果需要根据你的特定需求重写自动配置,可以通过以下方式执行:
# Register a ClientRegistrationRepository @Bean
下面的示例显示了如何注册ClientRegistrationRepository``@Bean
:
Java
@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();
}
}
Kotlin
@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://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()
}
}
# 提供一个WebSecurityConfigureRadapter
下面的示例展示了如何使用@EnableWebSecurity
提供WebSecurityConfigurerAdapter
并通过httpSecurity.oauth2Login()
启用OAuth2.0登录:
例2. OAuth2登录配置
Java
@EnableWebSecurity
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
}
}
Kotlin
@EnableWebSecurity
class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
}
}
# 完全覆盖自动配置
下面的示例展示了如何通过注册一个ClientRegistrationRepository``@Bean
并提供一个WebSecurityConfigurerAdapter
来完全覆盖自动配置。
例3.覆盖自动配置
Java
@Configuration
public class OAuth2LoginConfig {
@EnableWebSecurity
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
}
}
@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();
}
}
Kotlin
@Configuration
class OAuth2LoginConfig {
@EnableWebSecurity
class OAuth2LoginSecurityConfig: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
}
}
@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://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()
}
}
# Java 配置不需要 Spring 启动2.x
如果你不能使用 Spring Boot2.x,并且希望在CommonOAuth2Provider
中配置一个预定义的提供程序(例如,Google),请应用以下配置:
例4. OAuth2登录配置
Java
@Configuration
public class OAuth2LoginConfig {
@EnableWebSecurity
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
}
}
@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();
}
}
Kotlin
@Configuration
open class OAuth2LoginConfig {
@EnableWebSecurity
open class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
}
}
@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()
}
}
XML
<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>
← OAuth2.0登录 高级配置 →