WebFlux 系列松哥曾经连着写了十几篇了,Spring Security 系列之前更是发了 68 篇(公号后盾回复 ss 获取系列教程),不过之前这两个教程都是离开讲的,还没有把这两个交融到一起讲过。

随着 WebFlux 的倒退,咱们有必要来理解下在响应式编程中如何应用 Spring Security。明天松哥就通过一个简略的案例来和大家分享下如何在 WebFlux 中应用 Spring Security。

1.基于内存的应用

先来看一个简略的,就是把用户信息保留在内存中。

首先咱们来创立一个新的我的项目,引入 WebFlux 和 Spring Security 依赖,如下:

我的项目创立胜利后,咱们增加一个接口,用来获取登录用户信息,如下:

@RestControllerpublic 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》。

如果咱们想配置基于内存的用户信息,该怎么配置呢?增加如下配置类即可:

@Configurationpublic 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/test01spring.r2dbc.username=rootspring.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 接口,如下:

@Servicepublic 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 的用法,当然这里还有很多应用细节,在接下来的文章中松哥再和大家一一介绍。