Как настроить аутентификацию Spring WebFlux с помощью пользовательского AuthenticationConverter - PullRequest
0 голосов
/ 28 апреля 2020

поэтому я настраивал безопасность для своего API, где вы должны войти в систему с именем пользователя / паролем, получить токен JWT, а затем использовать его для всего остального. Вот как я настроил SecurityWebFilterChain:

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http
            .authorizeExchange()
            .pathMatchers("/login", "/")
            .permitAll()
            .and()
            .addFilterAt(UsernamePasswordAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
            .authorizeExchange()
            .pathMatchers("/api/**")
            .authenticated()
            .and()
            .addFilterAt(bearerAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION);

    return http.build();
}

, как вы можете видеть здесь, я установил два пользовательских фильтра. Один для имени пользователя / пароля и другой для токена на предъявителя (JWT).

Вот так я настраиваю фильтр UsernamePassword, где я предоставляю своему настраиваемому authManager пользовательскую службу UserDetails, кодировщик и обработчик успеха:

private AuthenticationWebFilter UsernamePasswordAuthenticationFilter() {
    UserDetailsRepositoryReactiveAuthenticationManager authManager;
    AuthenticationWebFilter usernamePasswordAuthenticationFilter;
    ServerAuthenticationSuccessHandler successHandler;


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

    usernamePasswordAuthenticationFilter = new AuthenticationWebFilter(authManager);
    usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(successHandler);

    return usernamePasswordAuthenticationFilter;
}

Это на самом деле работает, я могу отправить запрос GET с помощью curl или Postman следующим образом:

curl -v  -u username:password localhost:8080/login

и получить свой токен JWT обратно. классно. Всего одна проблема. По умолчанию этот фильтр использует

ServerHttpBasicAuthenticationConverter

Что я на самом деле хочу: Мне нужно отправить запрос POST с именем пользователя и паролем в теле запроса в простой JSON структуре вот так:

{
"username":"usr"
"password":"pass"
}

и используйте его для создания объекта аутентификации.

Это то, что я пробовал: Я создал и добавил пользовательский Преобразователь в мой AuthenticationFilter:

usernamePasswordAuthenticationFilter.setServerAuthenticationConverter(new UsernamePasswordAuthenticationConverter());

UsernamePasswordAuthenticationConverter:

public class UsernamePasswordAuthenticationConverter implements ServerAuthenticationConverter {
    @Override
    public Mono<Authentication> convert(ServerWebExchange exchange) {
        ...
    }
}

Здесь я застрял на несколько часов.

Question1 Как мне получить имя пользователя / пароль из JSON тела запроса и выдать Mono<Authentication> здесь? Я довольно новичок в реактивном программировании, извините, если это глупый вопрос.

Question2 Только GET-запросы, кажется, даже достигают этого пользовательского UsernamePasswordAuthenticationConverter. Почему? любые запросы POST отклоняются до этого, и я не понимаю, почему.

...