继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

WebFlux 和 Spring Security 会碰出哪些火花?

江南一点雨
关注TA
已关注
手记 318
粉丝 1.4万
获赞 3885

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

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP