1. 概述
从 Spring Security 5.1.x GA 版本开始,官方正式支持在 WebFlux 环境下使用 OAuth2 登录功能。
本文将介绍 如何在 WebFlux 应用中配置 OAuth2 登录支持,并讲解如何使用 WebClient
来访问受 OAuth2 保护的资源。
虽然 WebFlux 的 OAuth 登录配置方式与传统的 Web MVC 类似,但如果你还不太熟悉,可以先参考我们之前的文章:Spring OAuth2Login 配置详解。
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 找到:
3. 主控制器
接下来,我们添加一个简单的控制器,用于在首页显示用户名:
@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 账号登录。
步骤如下:
- 在 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. 使用自定义认证服务登录
我们也可以配置应用使用自定义的 OAuth2 授权服务器登录。
以下配置示例基于我们之前的一篇文章:REST API + Spring OAuth2 + AngularJS。
这次我们需要配置更多属性,而不仅仅是 Client ID 和 Secret:
spring:
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
⚠️ 注意事项:
- 需要指定 scope、grant type 和 redirect-uri
- 需要提供授权服务器的 authorization-uri 和 token-uri
- 最后还需要配置 UserInfo 接口,以便获取用户信息
6. 安全配置
默认情况下,Spring Security 会保护所有路径。如果只配置了一个 OAuth2 客户端,则会自动跳转到该客户端进行登录。
如果配置了多个客户端,Spring Security 会自动生成一个登录选择页面。
当然,你也可以自定义安全策略。比如:
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
public SecurityWebFilterChain configure(ServerHttpSecurity http) throws Exception {
return http.authorizeExchange(auth -> auth
.pathMatchers("/about").permitAll()
.anyExchange().authenticated())
.oauth2Login(Customizer.withDefaults())
.build();
}
}
✅ 在这个例子中,除了 /about
外的所有路径都需要认证。
7. WebClient 使用
OAuth2 不仅可以用来做登录,还可以结合 WebClient
访问受保护的资源。
配置 WebClient
@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrationRepo,
ServerOAuth2AuthorizedClientRepository authorizedClientRepo) {
ServerOAuth2AuthorizedClientExchangeFilterFunction filter =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepo, authorizedClientRepo);
return WebClient.builder().filter(filter).build();
}
调用受保护资源
@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
中的 Access Token 来调用远程接口。
8. 总结
这篇文章中,我们介绍了如何在 WebFlux 应用中集成 OAuth2 登录,并演示了如何使用 WebClient
调用 OAuth2 保护的资源。
📌 完整代码可参考 GitHub 仓库:Spring Reactive OAuth 示例