8. Spring Security 5.1之 OAuth 2.0 Login

1.OAuth 2.0 Login

OAuth 2.0登录功能为应用程序提供了使用OAuth 2.0提供程序(例如GitHub)或OpenID Connect 1.0提供程序(例如Google)上的现有帐户登录应用程序的功能。 OAuth 2.0 Login实现了用例:“使用Google登录”或“使用GitHub登录”。

OAuth 2.0登录是使用授权代码授予实现的,如OAuth
2.0授权框架和OpenID Connect Core 1.0中所指定。

1.1 Spring Boot 2.x Sample

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

本部分介绍如何使用Google作为身份验证提供程序配置OAuth 2.0登录示例,并介绍以下主题:

  • 1.1.1 初始化安装
  • 1.1.2 设置重定向 URI
  • 1.1.3 配置 application.yml
  • 1.1.4 启动 application

1.1.1 初始化安装

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

Google的OAuth 2.0身份验证实现符合OpenID
Connect1.0规范,并通过OpenID认证

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

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

1.1.2 设置重定向 URI

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

在“设置重定向URI”子部分中,确保将“授权重定向URI”字段设置为

http://localhost:8080/login/oauth2/code/google

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

1.1.3 配置 application.yml

既然您有一个新的OAuth客户端与Google,您需要配置应用程序以使用OAuth客户端进行身份验证流程

1.转到application.yml并设置以下配置

spring:
  security:
    oauth2:
      client:
        registration:   1
          google:   2
            client-id: google-client-id
            client-secret: google-client-secret

Example 6.1. OAuth Client properties

例6.1 OAuth客户端属性

  • 1 spring.security.oauth2.client.registration是OAuth客户端属性的基本属性前缀。
  • 2 基本属性前缀后面是ClientRegistration的ID,例如google。

1.1.4 启动application

启动Spring Boot 2.x示例并转到http://localhost:8080 然后,您将被重定向到默认的自动生成的登录页面,该页面显示Google的链接。

点击Google链接,然后您将重定向到Google进行身份验证。

使用您的Google帐户凭据进行身份验证后,显示给您的下一页是“同意”屏幕。 “同意”屏幕会要求您允许或拒绝访问您之前创建的OAuth客户端。 单击“允许”以授权OAuth客户端访问您的电子邮件地址和基本配置文件信息。

此时,OAuth客户端从UserInfo端点检索您的电子邮件地址和基本配置文件信息,并建立经过身份验证的会话。

1.2 Spring Boot 2.x Property Mappings

下表概述了Spring Boot 2.x OAuth客户端属性到ClientRegistration属性的映射:

Spring Boot 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 redirectUriTemplate
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].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].userNameAttribute providerDetails.userInfoEndpoint.userNameAttributeName

1.3 CommonOAuth2Provider

CommonOAuth2Provider为众多知名提供商预定义了一组默认客户端属性:Google,GitHub,Facebook和Okta。

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

如前所述,当我们配置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
  • 1registrationId设置为google-login。
  • 2provider属性设置为google,它将利用CommonOAuth2Provider.GOOGLE.getBuilder()中设置的客户端属性的自动默认。

1.4 Configuring Custom Provider Properties

有些OAuth 2.0提供程序支持多租户,这会导致每个租户(或子域)使用不同的协议端点。

例如,向Okta注册的OAuth客户端被分配给特定的子域并拥有自己的协议端点。

对于这些情况,Spring Boot 2.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)允许自定义配置协议端点位置。

1.5 Overriding Spring Boot 2.x Auto-configuration

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

它执行以下任务:

从配置的OAuth客户端属性注册由ClientRegistration组成的ClientRegistrationRepository @Bean。
提供WebSecurityConfigurerAdapter @Configuration并通过httpSecurity.oauth2Login()启用OAuth 2.0登录。
如果您需要根据具体要求覆盖自动配置,可以通过以下方式执行此操作:

  • 注册ClientRegistrationRepository @Bean
  • 提供WebSecurityConfigurerAdapter
  • 完全覆盖自动配置

注册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.BASIC)
            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
            .redirectUriTemplate("{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()启用OAuth 2.0登录:

@EnableWebSecurity
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .oauth2Login();
    }
}

完全覆盖自动配置

以下示例说明如何通过注册ClientRegistrationRepository @Bean并提供WebSecurityConfigurerAdapter来完全覆盖自动配置。

@Configuration
public class OAuth2LoginConfig {

    @EnableWebSecurity
    public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                .oauth2Login();
        }
    }

    @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.BASIC)
            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
            .redirectUriTemplate("{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();
    }
}

1.6 Java Configuration without Spring Boot 2.x

如果您无法使用Spring Boot 2.x并且想要在CommonOAuth2Provider中配置一个预定义的提供程序(例如,Google),请应用以下配置:

@Configuration
public class OAuth2LoginConfig {

    @EnableWebSecurity
    public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                .oauth2Login();
        }
    }

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

1.7 Additional Resources

以下附加资源描述了高级配置选项:

  • OAuth 2.0登录页面
  • 重定向端点
  • UserInfo端点:
    • 映射用户权限
    • 配置自定义OAuth2User
    • OAuth 2.0 UserService
    • OpenID Connect 1.0 UserService

你可能感兴趣的:(#,Spring,Security,译文)