使用WebFlux的Spring Security OAuth登录

2023/05/13

1. 概述

从5.1.x GA开始,Spring Security添加了对WebFlux的OAuth支持。

我们将讨论如何配置我们的WebFlux应用程序以使用OAuth2登录支持。我们还将讨论如何使用WebClient访问OAuth2安全资源。

Webflux 的OAuth登录配置类似于标准Web MVC应用程序的配置。有关这方面的更多详细信息,另请参阅我们关于Spring OAuth2 Login元素的文章。

2. Maven配置

首先,我们将创建一个简单的Spring Boot应用程序并将这些依赖项添加到我们的pom.xml中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>

Maven Central上提供了spring-boot-starter-securityspring-boot-starter-webfluxspring-security-oauth2-client依赖项。

3. RestController

接下来,我们将添加一个简单的控制器来在主页上显示用户名:

@RestController
public class MainController {

	@GetMapping("/")
	public Mono<String> index(@AuthenticationPrincipal Mono<OAuth2User> oauth2User) {
		return oauth2User
			.map(OAuth2User::getName)
			.map(name -> String.format("Hi, %s", name));
	}
}

请注意,我们将显示从OAuth2客户端UserInfo端点获得的用户名。

4. 使用谷歌登录

现在,我们将配置我们的应用程序以支持使用Google登录。

首先,我们需要在Google Developer Console新建一个项目。

现在,我们需要添加OAuth2凭据(Create Credentials > OAuth Client ID)。

接下来,我们将其添加到“Authorized Redirect URIs”:

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

然后,我们需要配置application.yml以使用Client ID和Secret:

spring:
    security:
        oauth2:
            client:
                registration:
                    google:
                        client-id: YOUR_APP_CLIENT_ID
                        client-secret: YOUR_APP_CLIENT_SECRET

由于我们的路径中有spring-security-oauth2-client,我们的应用程序将得到保护。

用户将被重定向到使用Google登录,然后才能访问我们的主页。

5. 使用Auth Provider登录

我们还可以将我们的应用程序配置为从自定义授权服务器登录。

在下面的示例中,我们将使用上一篇文章中的授权服务器。

这一次,我们需要配置更多的属性,而不仅仅是ClientID和Client Secret:

security:
    oauth2:
        client:
            registration:
                custom:
                    client-id: fooClientIdPassword
                    client-secret: secret
                    scopes: read,foo
                    authorization-grant-type: authorization_code
                    redirect-uri-template: http://localhost:8080/login/oauth2/code/custom
            provider:
                custom:
                    authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize
                    token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token
                    user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra
                    user-name-attribute: user_name

在这种情况下,我们还需要为OAuth2客户端指定 范围、 授权类型和重定向URI。我们还将提供授权服务器的授权和令牌URI。

最后,我们还需要配置UserInfo端点,以便能够获取用户身份验证详细信息。

6. 安全配置

默认情况下,Spring Security保护所有路径。因此,如果我们只有一个OAuth客户端,我们将被重定向到授权该客户端并登录。

如果注册了多个OAuth客户端,则会自动创建一个登录页面以选择登录方式。

如果愿意,我们可以更改它并提供详细的安全配置:

@EnableWebFluxSecurity
public class SecurityConfig {

	@Bean
	public SecurityWebFilterChain configure(ServerHttpSecurity http) throws Exception {
		return http.authorizeExchange()
			.pathMatchers("/about").permitAll()
			.anyExchange().authenticated()
			.and().oauth2Login()
			.and().build();
	}
}

在此示例中,我们保护了除“/about”之外的所有路径。

7. WebClient

除了使用OAuth2对用户进行身份验证之外,我们还可以做更多的事情。我们可以使用WebClient使用OAuth2AuthorizedClient访问OAuth2安全资源。

现在,让我们配置我们的WebClient:

@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrationRepo, ServerOAuth2AuthorizedClientRepository authorizedClientRepo) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction filter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepo, authorizedClientRepo);
    
    return WebClient.builder().filter(filter).build();
}

然后,我们可以检索OAuth2安全资源:

@Autowired
private WebClient webClient;

@GetMapping("/foos/{id}")
public Mono<Foo> getFooResource(@RegisteredOAuth2AuthorizedClient("custom") OAuth2AuthorizedClient client, @PathVariable final long id){
    return webClient
        .get()
        .uri("http://localhost:8088/spring-security-oauth-resource/foos/{id}", id)
        .attributes(oauth2AuthorizedClient(client))
        .retrieve()
        .bodyToMono(Foo.class); 
}

请注意,我们使用OAuth2AuthorizedClient中的AccessToken检索了远程资源Foo。

8. 总结

在这篇快速文章中,我们了解了如何配置WebFlux应用程序以使用OAuth2登录支持以及如何使用WebClient访问OAuth2安全资源。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章