首页 > 解决方案 > 使用 MongoDb 作为 UserDetails 存储的 Spring WebFlux 安全性

问题描述

O 我一直在为反应式 API 设置安全性,用户可以使用用户名/密码登录以获取 JWT 令牌,然后将其用于其他所有操作。用户详细信息(用户名、密码等)存储在 MongoDb 中。

我只是将过滤器添加到网络过滤器链中:

.addFilterAt(buildUsernamePasswordAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION)

在构建这个过滤器时,我给它我的自定义ApplicationUserService

    private AuthenticationWebFilter buildUsernamePasswordAuthenticationFilter() {
        UserDetailsRepositoryReactiveAuthenticationManager authManager;
        AuthenticationWebFilter usernamePasswordAuthenticationFilter;

        authManager = new UserDetailsRepositoryReactiveAuthenticationManager(applicationUserService);
        authManager.setPasswordEncoder(passwordEncoder);

        usernamePasswordAuthenticationFilter = new AuthenticationWebFilter(authManager);
        usernamePasswordAuthenticationFilter.setRequiresAuthenticationMatcher(ServerWebExchangeMatchers.pathMatchers(loginPathMatcher));
        return usernamePasswordAuthenticationFilter;
    }

ApplicationUserService看起来像:

@Service
public class ApplicationUserService implements ReactiveUserDetailsService {

    private final ReactiveUsersService reactiveUsersService;

    @Autowired
    public ApplicationUserService(ReactiveUsersService reactiveUsersService) {
        this.reactiveUsersService = reactiveUsersService;
    }

    @Override
    public Mono<UserDetails> findByUsername(String username) {
        return reactiveUsersService.getUserByUsername(username).cast(UserDetails.class).log();
    }
}

这用于ReactiveUsersService获取用户:

@Service
public class ReactiveUsersService {

    ReactiveUsersRepository repository;

    public ReactiveUsersService(ReactiveUsersRepository repository) {
        this.repository = repository;
    }

    public Flux<User> getUsers(){
        return repository.findAll().switchIfEmpty(Mono.error(new IllegalStateException("no users"))
        );
    }

    public Mono<User> getUserByUsername(String username){
        return repository.findByUsername(username);
    }
}

最后,ReactiveUsersRepository

@Repository
public interface ReactiveUsersRepository extends ReactiveMongoRepository<User, Integer> {

    Mono<User> findByUsername(String username);
}

通过此设置,我没有收到任何错误,但登录不起作用。我只是得到 401 回来。请注意,我已.log()添加到获取用户的位置。这是它记录的内容:

2020-05-06 17:23:54.741  INFO 23348 --- [ctor-http-nio-3] reactor.Mono.MapFuseable.1               : | onSubscribe([Fuseable] FluxMapFuseable.MapFuseableSubscriber)
2020-05-06 17:23:54.742  INFO 23348 --- [ctor-http-nio-3] reactor.Mono.MapFuseable.1               : | request(unbounded)
2020-05-06 17:23:54.743  INFO 23348 --- [ctor-http-nio-3] reactor.Mono.MapFuseable.1               : | onContextUpdate(Context2{interface org.springframework.web.server.ServerWebExchange=org.springframework.web.server.adapter.DefaultServerWebExchange@750265e1, interface org.springframework.security.core.context.SecurityContext=MonoFlatMap})
2020-05-06 17:23:54.743  INFO 23348 --- [ctor-http-nio-3] reactor.Mono.MapFuseable.1               : | onContextUpdate(Context2{interface org.springframework.web.server.ServerWebExchange=org.springframework.web.server.adapter.DefaultServerWebExchange@750265e1, interface org.springframework.security.core.context.SecurityContext=MonoFlatMap})
2020-05-06 17:23:54.744  INFO 23348 --- [ctor-http-nio-3] reactor.Mono.MapFuseable.1               : | onContextUpdate(Context2{interface org.springframework.web.server.ServerWebExchange=org.springframework.web.server.adapter.DefaultServerWebExchange@750265e1, interface org.springframework.security.core.context.SecurityContext=MonoFlatMap})
2020-05-06 17:23:54.825  INFO 23348 --- [ntLoopGroup-2-2] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:3, serverValue:104}] to localhost:27017
2020-05-06 17:23:54.844  INFO 23348 --- [ntLoopGroup-2-2] reactor.Mono.MapFuseable.1               : | onNext(User{id='5eb10474d388c2b64f709b4c', username='admin', email='admin@admin.com', password='$2a$10$qj83J33wn7l9IpNvAlAFQ.fDxaQGwl5Pw4nHRho.Y2wWs1goJny5e', roles=null})
2020-05-06 17:23:54.854  INFO 23348 --- [ntLoopGroup-2-2] reactor.Mono.MapFuseable.1               : | cancel()
2020-05-06 17:23:54.854  INFO 23348 --- [ntLoopGroup-2-2] reactor.Mono.MapFuseable.1               : | onContextUpdate(Context2{interface org.springframework.web.server.ServerWebExchange=org.springframework.web.server.adapter.DefaultServerWebExchange@750265e1, interface org.springframework.security.core.context.SecurityContext=MonoFlatMap})
2020-05-06 17:23:54.855  INFO 23348 --- [ntLoopGroup-2-2] reactor.Mono.MapFuseable.1               : | onComplete()

ApplicationUserService之前,我在我使用InMemoryUsersService的有几个硬编码用户而不是“ReactiveUsersServe”的地方插入了 MongoDb,并且一切正常。本质上,我只是更改了这一行以从 Mongo 而不是内存中获取用户:

return reactiveUsersService.getUserByUsername(username).cast(UserDetails.class).log();

似乎它确实从 Mongo 获取用户,但未能对其进行身份验证。它没有给我任何错误或任何东西,而且我是这个反应弹簧的新手。我正在努力调试它并获得任何可以掌握的东西。

标签: javamongodbspring-securityspring-webflux

解决方案


推荐阅读