松哥原創的 Spring Boot 視訊教程已經殺青,感興趣的小夥伴戳這裡-->Spring Boot+Vue+微人事視訊教程
WebFlux 系列松哥已經連着寫了十幾篇了,Spring Security 系列之前更是發了 68 篇(公号背景回複 ss 擷取系列教程),不過之前這兩個教程都是分開講的,還沒有把這兩個融合到一起講過。
随着 WebFlux 的發展,我們有必要來了解下在響應式程式設計中如何使用 Spring Security。今天松哥就通過一個簡單的案例來和大家分享下如何在 WebFlux 中使用 Spring Security。
1.基于記憶體的使用
先來看一個簡單的,就是把使用者資訊儲存在記憶體中。
首先我們來建立一個新的項目,引入 WebFlux 和 Spring Security 依賴,如下:

項目建立成功後,我們添加一個接口,用來擷取登入使用者資訊,如下:
@RestController
public class UserController {
@GetMapping("/user")
public Mono<Principal> getCurrentUser(Mono<Principal> principal) {
return principal;
}
}
複制
注意我們的傳回值是
Mono<Principal>
,接口的參數也是支援
Mono<Principal>
的。
這就可以了,接下來我們啟動項目,在啟動的過程中,控制台就會列印出預設的使用者密碼,拿着預設的使用者密碼以及預設使用者名 user 去登入,登入完成後就可以通路
/user
接口了,這個過程和普通的 Spring Security 用法并沒有什麼差異,是以我就不多說了,如果大家對普通的 Spring Security 用法還不熟悉,也可以看看松哥的新書《深入淺出 Spring Security》。
如果我們想配置基于記憶體的使用者資訊,該怎麼配置呢?添加如下配置類即可:
@Configuration
public class SecurityConfig {
@Bean
MapReactiveUserDetailsService mapReactiveUserDetailsService() {
UserDetails ud1 = User.withUsername("admin")
.password("{noop}123")
.roles("admin")
.build();
UserDetails ud2 = User.withUsername("zhangsan")
.password("{noop}123")
.roles("user")
.build();
return new MapReactiveUserDetailsService(ud1, ud2);
}
}
複制
隻需要提供一個 MapReactiveUserDetailsService 執行個體即可。
MapReactiveUserDetailsService 實作了 ReactiveUserDetailsService 接口,ReactiveUserDetailsService 接口其實就跟我們以前的 UserDetailsService 接口的作用差不多;而 MapReactiveUserDetailsService 則類似于我們以前的 InMemoryUserDetailsManager,都是基于記憶體來管理使用者的,了解了這一層,剩下的東西就好懂了。
我們在 MapReactiveUserDetailsService 中提供兩個使用者對象即可。
最後啟動項目,此時 IDEA 控制台就不會輸出預設生成的密碼了,這個時候我們就可以直接使用 admin/123 或者 user/123 來進行登入了。
2.基于資料庫的使用
第一小節我們是在記憶體中配置使用者,真正到了開發中我們還是需要從資料庫中讀取使用者資料,是以接下來我們再來看一個基于資料庫的配置。
首先我們先來大概看一眼資料庫:
首先我們建立項目,這個時候要添加的依賴就比較多,除了 WebFlux 和 Spring Security 之外,還有 R2DBC 以及 MySQL 驅動,如下:
項目建立成功之後,在 application.properties 中配置資料庫基本資訊,如下:
spring.r2dbc.url=r2dbcs:mysql://localhost:3306/test01
spring.r2dbc.username=root
spring.r2dbc.password=123
複制
如此之後,我們的準備工作就算完成了。
接下來我們建立 User 的實體類,老規矩,User 類需要實作 UserDetails 接口:
public class User implements UserDetails {
@Id
private Long id;
private String username;
private String address;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
複制
接下來建立 UserRepository:
public interface UserRepository extends ReactiveCrudRepository<User,Long> {
Mono<UserDetails> findUserByUsername(@Param("username") String username);
}
複制
增加了一個 findUserByUsername 方法,用來根據使用者名查找使用者對象。
接下來定義 UserService,這次需要我們自己實作 ReactiveUserDetailsService 接口,如下:
@Service
public class UserService implements ReactiveUserDetailsService {
@Autowired
UserRepository userRepository;
@Override
public Mono<UserDetails> findByUsername(String username) {
return userRepository.findUserByUsername(username);
}
}
複制
UserService 實作了 ReactiveUserDetailsService 接口,并重寫了 findByUsername 方法,這個類似于我們之前重寫 UserDetailsService#loadUserByUsername 方法。
這裡記得将 UserService 注冊到 Spring 容器中,接下來就不需要額外的工作了。
配置完成了。
接下來我們啟動項目,此時就可以通過資料庫中的使用者進行登入了。
3.小結
好啦,今天就通過兩個簡單的小案例,帶領小夥伴們體驗下 WebFlux+Spring Security 的用法,當然這裡還有很多使用細節,在接下來的文章中松哥再和大家一一介紹。