Безопасность Spring WebFlux с MongoDb в качестве хранилища UserDetails - PullRequest
0 голосов
/ 06 мая 2020

O Я настраивал безопасность для реактивного API, когда пользователи могут войти в систему с именем пользователя / паролем, чтобы получить токен JWT, а затем использовать его для всего остального. Данные пользователя (имя пользователя, пароль и т. Д. c, др. c) хранятся в 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()

Раньше я подключал MongoDb к ApplicationUserService. Я использовал InMemoryUsersService, где у меня было несколько жестко заданных пользователей вместо ReactiveUsersSercvce, и все работало нормально. По сути, я просто изменил эту строку, чтобы получить пользователей из Mon go вместо памяти:

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

Кажется, что он DID получил пользователя из Mon go, но не смог его аутентифицировать. Это не дает мне никаких ошибок или чего-то еще, и я новичок в этой реактивной пружине. Я изо всех сил пытаюсь отладить это и получить что-нибудь для gr asp.

...